Can the implementation of a virtual function be pu

2019-05-28 10:22发布

问题:

usually if we put an implementation of a non-virtual member function in the header file that function would be inlined. how about if we put the implementation of a virtual member function in the header file? I guess it would be the same as putting it in the cpp file because inlining and polymorphism do not work together. Am I right on this?

回答1:

Putting the implementation of a method in the header file doesn't make it inline. Putting it in the class declaration does. I'll assume that's what you meant from now on.

What is important here is that declaring a function inline is only an information to the compiler, it does not necessarily make that function inline

Most of the time, the compiler will just ignore this and the method won't be inlined.

It's possible to have a virtual method inline though, as stated in the c++ faq (http://www.parashift.com/c++-faq-lite/inline-virtuals.html) : "The only time an inline virtual call can be inlined is when the compiler knows the "exact class" of the object which is the target of the virtual function call. This can happen only when the compiler has an actual object rather than a pointer or reference to an object. I.e., either with a local object, a global/static object, or a fully contained object inside a composite."

In short, the compiler will inline a virtual method only if you don't use dynamic link resolution (we could say, "when we don't use the virtual").



回答2:

It is the same as for normal member functions. However, since you usually call virutal functions through a object pointer they cannot really be inlined, so it often is not that useful. They can still be inlined though if you call them directly on a object, so it is not neccessary a waste.



回答3:

A compiler is able to inline a virtual method if it can be sure at compile time which method will be called. For example, if you've got:

class Base
{
public:
  virtual void Print() {std::cout << "Base" << std::endl;}
};

class Derived : public Base
{
public:
  virtual void Print() {std::cout << "Derived" << std::endl;}
};

then if you say:

Derivded d;
d.Print();

The compiler is able to inline the call to Print as it can determine at compile time which version is being called, as polymorphism only happens through call made via a pointer or reference.



回答4:

You may put the implementation into a header file.

There are occasions when, even if the function is virtual, the compiler can determine that this implementation will be called and may be able to inline it.

In the most general scenarios where you have just a pointer or reference to the class it will not be inlined.

A case where it would be is where you specify the class name from its own member function.

class MyBase
{ 
 protected:
  int m_x;
  virtual void myFunc()
  {
      ++m_x; // trivial implementation that is a good target for inlining
  }
};

   // probably somewhere else in your code
class MyDerived : public MyBase
{
      void myFunc() 
       { // not necessarily implemented in the header

         for( size_t i = 0; i < 10000; ++i )
         {
               MyBase::myFunc(); // compiler knows what function
                     // it is calling and
                      // might inline it if appropriate
         }
      }
 };