inline virtual function

Can a virtual function be also inline ?
please explain the issue to me .
LVL 1
ronen_diAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

IexpertCommented:
No,
Because the way virtual functions are implemented in C++
is that an array of function pointers (the vtable) is automatically
built for each class. Inline functions are resolved at compile
time by the compiler and hence the call through a function
pointer can't be used.
0
jasonclarkeCommented:
You can declare a virtual function inline the same as you can any other C++ function.  However the compiler is almost never likely to take any notice of the request (inline is a hint to the compiler, nothing more, so the compiler is free to ignore it).

The problem is that virtual function calls are not resolved until run-time.  That is the code to be executed cannot be determined until run time, and hence the compiler cannot inline the code to be called.  

Remember that virtual methods may not even be recompiled when another derived class is added, so any 'inlining' of this sort would have to be left to link time - so effectively you would need a 'smart' linker.  I am not aware of any that can do this.
0
KangaRooCommented:
virtual functions -> run time resolved
inline -> compile time 'injected' code
=> Nope, you can't 'inline' virtual functions
0
Determine the Perfect Price for Your IT Services

Do you wonder if your IT business is truly profitable or if you should raise your prices? Learn how to calculate your overhead burden with our free interactive tool and use it to determine the right price for your IT services. Download your free eBook now!

jasonclarkeCommented:
As an example consider the following:

file Base.h:

class Base
{
public:
   virtual void f() = 0;
}

class Derived : public Base
{
public:
   virtual void f() {
       // Do Something
   }
};

void processSet(vector<Base*>& bvec);

and in Base.cpp

#include "Base.h"

void processSet(vector<Base*>& bvec)
{
    for (int i=0; i<bvec.size(); i++)
         bvec[i]->f();
}

and main.cpp

#include "Base.h"

void main()
{
    vector<Base*> bvec;
    bvec.push_back(new Derived);
    processSet(bvec);
}

In this situation you could argue that the call to bvec[i]->f() could be inlined since there is only one possible expansion.  However the compiler *cannot* do this because things may change without Base.cpp being recompiled.  So, if you changed main.cpp to:

#include "Base.h"

class MyDerived : public Base
{
public:
   virtual void f() {
      // Do Something Else
   }
};

void main()
{
    vector<Base*> bvec;
    bvec.push_back(new Derived);
    bvec.push_back(new MyDerived);
    processSet(bvec);
}

you would expect everything to work without recompiling Base.cpp.  So the compiler could not have done the inline expansion when it compiled Base.cpp.  The linker could -conceivably- have made this decision,  but I think that sort of behaviour is way beyond the sort of thing that most linkers could do.

0
abdijCommented:
The literal answer to your question is Yes. Virtual functions can be inline functions. But the purpose of making a particular function inline is not achieved because the "inline" is a request to the compiler to include the code as it occurs, instead of creating a Call to the function ( more memory (inline) vs  less overhead (stacks etc for functions). Since the virtual functions are resolved at run time the compiler will have alredy ignored your request to make the "virtual function inline". The inline virtual function will be treated as a normal virtual function ( Call to function is generated ).

The following class when compiled (ofcourse with other code written to support it ) will compile fine.

// class begins
class CInlineClass
{
// Attributes
public:

      CInlineClass();          
      inline virtual void Hi(void)
      {
            MessageBox("Hi", "Abdij", MB_OK);
      }
      virtual ~CInlineClass();
} // end of class

// on some event in some portion of your code you can have

some function
{

 CInlineClass  oInline;

 oInline.Hi();

}

When the some function is executed it will display a Message box sayin "Hi".

But the point is the virtual function is not inlined but called.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
LucHoltkampCommented:
It depends on implementation of the compiler, for instance:

struct A
{
  virtual void f() { cout << "A::f()"; }
};

struct B : A
{
  virtual void f() { cout << "B::f()"; }
};

void test()
{
  B b;
  A *a = &b;
  b.f();   // resolved at compile time, code is emitted directly (inline!)
  a->f(); // resolved at run time, VTABLE entry call is used
};

So inline virtual CAN make sense, it depends on compiler implementation. Notice, that instead of jasonclarckes example, this is a clear situation for the compiler, b.f() can always be resolved at compiletime.
BTW I tested it with VC6, and this is exactly what happens, b.f() is indeed emitted inline, while for a->f() the VTABLE entry is called.
Luc
0
KangaRooCommented:
How does VC respond to the following scenario (can't test myself, gcc ignores the inline request in this case =)

// inline.h ==========================
#include <stdio.h>

struct A
{
   virtual void f();
   // other stuff  
};


void g1();
void g2();
//=======================================================
// inline1.cpp =======================
#include "inline.h"

inline void A::f()
{puts("inline variant");}
void g1()
{
   A a;
   a.f();
}
//=======================================================
// inline2.cpp =======================
#include "inline.h"

//void A::f()
//{puts("virtual variant");}

void g2()
{
   A a;
   a.f();
}
//=======================================================
// inline.cpp ========================
#include "inline.h"

int main()
{
   g1();
   g2();
}
//=======================================================
0
LucHoltkampCommented:
You mean the following scenario (your example could be clearer KangaRoo):
struct A
{
  virtual void f() { cout << "A::f()"; } // inline
};

struct B : A
{
  virtual void f(); // outline
};
void B::f() { cout << "B::f()"; }

void test()
{
  A a; a.f();
  B b; b.f();
};
In test the code for A::f() is emitted inline. the function B::f() is called directly, so the VTABLE entry is not used.
Conclusion, if VC6 can resolve the function at compile-time it uses a direct function call or emits the code directly inline, only if the function cannot be resolved at compile time it uses the VTABLE entry.
In fact I like that, good piece of optimization here...
Not that it is really important, the execution-time overhead of late binding is not that great,  just an extra mov to load the VTABLE into a register.
Luc
0
KangaRooCommented:
You wouldn't be a good tester :-)) Off course that will work.
My example is an attempt to trip up VC's inlining strategie.
0
LucHoltkampCommented:
Same thing happens again: in g1() the code is emitted inline, in g2() the function is called directly.
(I asume ofcourse that A::f shouldn't be commented out in inline2.cpp, otherwise it won't compile)
0
KangaRooCommented:
Oeps. yes.
This means two different 'versions' of A::f are generated. Doesn't that sound like a potential source for trouble?
0
LucHoltkampCommented:
Yes it does, but that goes for all compilers.... this is not specific VC.
I mean, f() does not need to be virtual to let this construction cause a potential bug, if you declare a prototype, and in one source file define the function, and in the other define it as an inline, no compiler will complain, and the linker won't notice it, because the inline is not linked.
In any case, C++ doesn't protect you from being stupid...
Luc
0
KangaRooCommented:
I admit, it is far fetched...
0
jasonclarkeCommented:
> Not that it is really important, the
> execution-time overhead of late
> binding is not that great,  just an
> extra mov to load the VTABLE into a
register.

right the overhead of a virtual function call as compared to a normal function call is usually insignificant.  But the overhead of a function call compared to no function call can be significant, which is why you have to take care in performance critical code if you have lots of 'small' virtual methods...

> This means two different 'versions' of A::f are generated.

compilers certainly used to behave that way, if an in-line function could not be 'in-lined' then one function would likely be generated for each compilation unit.  However, I think the standard now says that if a function is not 'in-lined' there will be only one definition - so I am not sure how VC++ can deal with this requirement behaving as you describe/  
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Web Languages and Standards

From novice to tech pro — start learning today.