[英]pure virtual function with implementation in C++
我知道,可以将基类中的纯虚函数实现为默认实现。 但是我不太明白下面的代码。
class A {
public:
virtual void f1() = 0;
virtual void f2() = 0;
};
void A::f1(){
cout << "base f1" << endl;
f2();
}
void A::f2(){
cout << "base f2" << endl;
}
class B: public A {
public:
void f1() { A::f1(); }
void f2() { cout << "derived f2" << endl; }
};
int main(){
B b;
b.f1();
}
为什么B :: f1()调用B :: f2()而不是A :: f2。 我知道它会以这种方式运行,但是为什么呢? 我错过了哪些基本知识。
另一个问题,基类中纯虚函数的实现是否使pure(= 0)不必要?
这是C ++标准为虚拟函数定义的行为:调用可用的最多派生类型的版本。
当然,对于普通对象,最派生的类型是对象本身之一:
B b;
b.f1(); // of course calls B's version
有趣的是,如果您有指针或引用:
B b;
A& ar = b;
A* ap = &b;
// now both times, B's version will be called
ar.f1();
ap->f1();
在 f1 内部也会发生相同的情况,实际上,您隐式地这样做:
this->f2(); // 'this' is a POINTER of type A* (or A const* in const functions).
当不发生这种情况时会出现一种现象(以下示例需要一个复制构造函数):
B b;
A a = b; // notice: not a pointer or reference!
A.f1(); // now calls A's version
实际发生的情况是,仅将b
的A
部分复制到a
,而B
部分被删除,因此a
实际上是一个真实的,非派生的A
对象。 这就是所谓的“对象切片”,这是您不能在std::vector
使用基础对象来存储多态对象的原因,而需要指针或引用。
返回虚拟函数:如果您对技术细节感兴趣,可以通过虚拟函数表(简短的vtable)来解决。 请注意,这只是事实上的标准,C ++不需要通过vtables实现(实际上,其他支持多态性/继承的语言,例如Java或Python,也都实现了vtables)。
对于类中的每个虚函数,在其对应的vtable中都有一个条目。
普通函数被直接调用(即,执行到函数地址的无条件分支)。 相反,对于虚拟函数调用,我们首先需要在vtable中查找地址,然后才能跳转到存储在其中的地址。
现在,派生类将复制其基类的vtable(因此最初它们包含的地址与基类表的地址相同),但是只要您覆盖了函数,就替换相应的地址。
顺便说一句:您可以告诉编译器不要使用vtable,而是显式调用特定的变体:
B b;
A& a = b;
a.A::f1(); // calls A's version inspite of being virtual,
// because you explicitly told so
b.A::f1(); // alike, works even on derived type
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.