C++ 能否将虚拟函数的实现放在头文件中
通常,如果我们将非虚拟成员函数的实现放在头文件中,该函数将内联。如果我们将虚拟成员函数的实现放在头文件中如何?我想这和把它放在cpp文件中是一样的,因为内联和多态不能一起工作。我说的对吗?将方法的实现放在头文件中不会使其内联。把它放在类声明中就行了。我想从现在起你就是这个意思 这里重要的是,声明函数内联只是编译器的一个信息,它不一定使该函数内联 大多数情况下,编译器只会忽略这一点,而方法不会内联 <> p>有可能有一个内联的虚拟方法,如C++ FAQ()中所述: 内联虚拟调用唯一可以内联的时间是编译器知道“精确类”时作为虚拟函数调用目标的对象的。只有当编译器有一个实际的对象而不是一个指向对象的指针或引用时,才会发生这种情况。即,使用本地对象、全局/静态对象或组合中完全包含的对象。”C++ 能否将虚拟函数的实现放在头文件中,c++,header,virtual,inline,C++,Header,Virtual,Inline,通常,如果我们将非虚拟成员函数的实现放在头文件中,该函数将内联。如果我们将虚拟成员函数的实现放在头文件中如何?我想这和把它放在cpp文件中是一样的,因为内联和多态不能一起工作。我说的对吗?将方法的实现放在头文件中不会使其内联。把它放在类声明中就行了。我想从现在起你就是这个意思 这里重要的是,声明函数内联只是编译器的一个信息,它不一定使该函数内联 大多数情况下,编译器只会忽略这一点,而方法不会内联 p>有可能有一个内联的虚拟方法,如C++ FAQ()中所述: 内联虚拟调用唯一可以内联的时间是编译
简而言之,只有在不使用动态链接解析的情况下,编译器才会内联虚拟方法(我们可以说,“当我们不使用虚拟方法时”).这与普通成员函数相同。但是,由于您通常通过对象指针调用virutal函数,因此它们不能真正内联,因此通常不太有用。但是如果您直接在对象上调用它们,它们仍然可以内联,因此不必浪费。编译器能够内联虚拟方法如果可以确定在编译时将调用哪个方法。例如,如果您有:
class Base
{
public:
virtual void Print() {std::cout << "Base" << std::endl;}
};
class Derived : public Base
{
public:
virtual void Print() {std::cout << "Derived" << std::endl;}
};
编译器能够内联调用
Print
,因为它可以在编译时确定调用哪个版本,因为多态性只能通过通过指针或引用进行调用发生。您可以将实现放入头文件中
在某些情况下,即使函数是虚拟的,编译器也可以确定将调用此实现,并且可以将其内联
在最常见的场景中,您只有一个指向类的指针或引用,它不会被内联
在这种情况下,您可以从自己的成员函数中指定类名
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
}
}
};
类MyBase
{
受保护的:
int m_x;
虚拟void myFunc()
{
++m_x;//这是一个很好的内联目标的平凡实现
}
};
//可能是代码中的其他地方
类MyDerived:publicmybase
{
void myFunc()
{//不一定在头中实现
对于(尺寸i=0;i<10000;++i)
{
MyBase::myFunc();//编译器知道什么函数
//它正在呼叫和
//如果合适的话,我们可以将其内联
}
}
};
只使用<代码>内联应作为控制联动IMO的工具。用C++ <代码>最终< /C> >(添加到类或方法中),编译器有更多的机会来内联:
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
}
}
};