通常如果我们在头文件中放置一个非虚拟成员函数的实现,那么函数将被内联。如果我们在头文件中放置虚拟成员函数的实现怎么样?我想这与把它放在cpp文件中是一样的,因为内联和多态不能一起工作。我是对的吗?
答案 0 :(得分:3)
将方法的实现放在头文件中不会使其内联。把它放在类声明中。我认为这就是你从现在开始的意思。
这里重要的是声明一个内联函数只是编译器的一个信息,它不一定使该函数内联
大多数情况下,编译器只会忽略它,并且不会内联该方法。
但是,如c ++ faq(http://www.parashift.com/c++-faq-lite/inline-virtuals.html)中所述,可以使用内联的虚方法: “内联虚拟调用唯一可以内联的是编译器知道作为虚函数调用目标的对象的”确切类“。这只有在编译器具有实际对象而不是指针时才会发生。引用一个对象。即,使用本地对象,全局/静态对象或复合内部的完全包含的对象。“
简而言之,只有当您不使用动态链接解析时,编译器才会内联虚拟方法(我们可以说,“当我们不使用虚拟”时)。
答案 1 :(得分:1)
与普通成员函数相同。但是,由于您通常通过对象指针调用虚拟函数,因此它们无法真正内联,因此通常没有那么有用。如果你直接在一个对象上调用它们,它们仍然可以被内联,所以它不是必要的浪费。
答案 2 :(得分:1)
如果编译器可以确定将调用哪个方法,则编译器能够内联虚拟方法。例如,如果你有:
class Base
{
public:
virtual void Print() {std::cout << "Base" << std::endl;}
};
class Derived : public Base
{
public:
virtual void Print() {std::cout << "Derived" << std::endl;}
};
然后如果你说:
Derivded d;
d.Print();
编译器能够内联对Print
的调用,因为它可以在编译时确定调用哪个版本,因为多态只通过指针或引用进行调用。
答案 3 :(得分:1)
您可以将实现放入头文件中。
有时,即使函数是虚函数,编译器也可以确定将调用此实现并且可以内联它。
在大多数情况下,你只有一个指针或类的引用,它将不会内联。
在某种情况下,您可以从自己的成员函数中指定类名。
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
}
}
};