【发布时间】:2019-04-14 09:01:22
【问题描述】:
这个问题和What are the differences between overriding virtual functions and hiding non-virtual functions?有点关系,但我问的不是技术细节,而是非虚函数和虚函数的使用。
这里有一点背景。假设我有一个基类 A 和两个派生类 B 和 C
#include <iostream>
class A {
public:
A() {};
virtual void foo() { std::cout << "foo() called in A\n"; };
virtual void bar() { std::cout << "bar() called from A\n"; };
void xorp() { std::cout << "xorp() called from A\n"; };
virtual ~A() {};
};
class B : public A {
public:
B() {};
virtual ~B() {};
virtual void foo() override { std::cout << "foo() called in B\n"; };
//virtual void bar() override not implemented in B, using A::bar();
};
class C : public A {
public:
C() {};
virtual ~C() {};
virtual void foo() override { std::cout << "foo() called in C\n"; };
//virtual bar() override not implemented in C, using A::bar();
};
int main() {
A a{};
B b{};
C c{};
a.foo(); //calls A::foo()
a.bar(); //calls A::bar()
a.xorp(); //calls non-virtual A::xorp()
b.foo(); //calls virtual overridden function B::foo()
b.bar(); //calls virtual non-overridden function A::bar()
b.xorp(); //calls non-virtual A::xorp()
c.foo(); //calls virtual overridden function C::foo()
c.bar(); //calls virtual non-overridden function A::bar()
c.xorp(); //calls non-virtual A::xorp()
return 0;
}
正如预期的那样,这会输出以下内容:
foo() called in A
bar() called from A
xorp() called from A
foo() called in B
bar() called from A
xorp() called from A
foo() called in C
bar() called from A
xorp() called from A
如果我在派生类中未实现虚函数 bar(),则派生类 B 和 C 中对 bar() 的任何调用都会解析为 A::bar()。 xorp() 是一个非虚函数,也可以从派生类中调用为 b.xorp() 或 b.A::xorp()。
例如,如果我要在 B 中实现 xorp(),它将有效地隐藏 A::xorp(),并且对 b.xorp() 的调用实际上是对 bB::xorp() 的调用.
这让我想到了我的问题,使用上面的例子。假设我有一个派生类实现所需的辅助函数。
辅助函数是非虚成员函数(如 xorp())与辅助函数是派生类不覆盖的虚函数(bar())之间有区别吗? /强>?
通读这个关于类对象布局和 VTABLE 的演示文稿(https://www.cs.bgu.ac.il/~asharf/SPL/Inheritance.pptx,幻灯片 28-35)我无法真正发现区别,因为非虚拟和非覆盖的虚拟函数都指向同一个地方(即基类中的函数)
谁能给我一个例子,说明这两种方法会产生不同的结果,或者是否有我没有发现的警告?
【问题讨论】:
-
没有区别。但是派生类可能会覆盖该函数。通常的警告是,您不知道它何时发生,是谁做的以及他为什么选择这样做。并且可以打破你的班级这样做。这些是您在设计时必须考虑的高风险因素。很难正确地做。幸运的是,有一个非常简单的解决方案,声明类
final。这可能会在未来某个时间产生一个电话,但它可以消除所有这些风险。 -
这里没有使用虚拟继承。
标签: c++ overriding virtual-functions name-hiding