可以将在基类中未内联的纯虚方法内联为子类
Can subclass inline a pure virtual method that is not inline in the base?
据我所知,编译器可以在编译时知道对象在运行时的类型(c++ faq)时内联虚函数调用。
但是,当从基类实现纯虚方法时会发生什么?同样的规则也适用吗?下面的函数调用是内联的吗?
class base
{
public:
virtual void print() = 0;
virtual void callPrint()
{
print(); // will this be inline?
}
};
class child : public base
{
public:
void print() { cout << "hellon"; }
};
int main()
{
child c;
c.callPrint();
return 0;
}
编辑:我认为我原来的示例代码实际上是我想问的问题的一个糟糕的表示。我已经更新了代码,但问题仍然是一样的。
编译器从未被要求内联函数调用。在这种情况下,允许内联函数调用,因为它知道c
的具体类型(因为它不是通过指针或引用间接的,编译器可以看到它被分配为child
的位置)。因此,编译器知道使用的是print()
的哪个实现,可以选择不间接执行vtable,进一步选择内联函数的实现。
child::print()
的直接调用,或者间接地通过虚函数表插入。
这些优化通常归结为"as-if"规则——编译器必须表现得就好像在间接执行一个完整的虚变量表——这意味着结果必须是相同的,但是如果结果相同,编译器可以选择不同的方法来实现结果。这包括内联等
答案当然是"视情况而定",但原则上没有优化的障碍。事实上,你甚至没有在这里做任何多态,所以这真的很直接。
如果你有这样的代码,这个问题会更有趣:
child c;
base & b = c;
b.print();
关键是编译器此时知道动态分派的最终目标是什么(即child::print()
),因此可以进行优化。(当然,有两个单独的优化机会:一个是避免动态分派,另一个是使目标函数体在TU中可见。)
您只需要注意以下几条规则:
1)编译器永远不会被强制内联——即使使用指令或在头文件中定义方法。
2)多态性必须总是有效的。这意味着当存在动态调用的可能性时,编译器将更倾向于通过vftable调用函数,而不是将其内联。
相关文章:
- 从父类方法返回子类对象
- c++, 在子类中,如何在没有对象的情况下访问父类的方法?
- 将子类方法声明为基类的友元
- 使用模板参数重载C++方法:如何使其适用于模板的子类?
- C++有没有办法强制重写一组方法,如果其中一个方法在子类中具有重写?
- C ++类型特征:确保子类实现方法
- 函数从唯一代码调用正确的子类方法
- Arduino在子类中使用父类方法
- C++强制在子类中实现方法,但具有不同的签名
- 我们可以在没有新实例化的情况下声明一个抽象方法来返回抽象超类中的子类对象吗
- 如何调用传递给 JNI 'jobject' 的 Java 对象的子类/子类的方法
- 将方法参数类型更改为子类中的派生类
- 如果指针的子类的方法对于子类是唯一的,如何访问这些方法?
- C++继承,如何在基类的方法中调用子类的方法?
- 在子类上调用模板化静态方法时获取类的类型名
- 检查子类是否执行了方法重写
- 将"this"从父类方法转换为子类方法是一种好的做法吗?
- 从C++中的父类实例访问子类方法
- 基类中的虚拟方法和子类中的非 Virtula 方法.仍然如何调用子类方法,即使它是非虚拟的
- C ,基础课程如何将子类作为成员包含并调用其方法