我最近遇到了以下类型的代码:
struct A {
virtual void foo() = 0;
};
struct B : public A {
virtual void foo() = 0;
};
struct C : public B {
virtual void foo() override {
}
};
Run Code Online (Sandbox Code Playgroud)
重新声明纯虚方法有什么目的吗?
更重要的是:这会改变语义吗?即B::foo隐藏A::foo并引入新的 vftable?
如果A::foo实际上不是纯虚拟但提供了一个实现(仍然为我编译),那么在上面的示例中会发生什么?
查看cppreference中的示例 :
Run Code Online (Sandbox Code Playgroud)struct Abstract { virtual void f() = 0; // pure virtual }; // "Abstract" is abstract struct Concrete : Abstract { void f() override {} // non-pure virtual virtual void g(); // non-pure virtual }; // "Concrete" is non-abstract struct Abstract2 : Concrete { void g() override = 0; // pure virtual overrider }; // "Abstract2" is abstract int main() { // Abstract a; // Error: abstract class Concrete b; // OK Abstract& a = b; // OK to reference abstract base a.f(); // virtual dispatch to Concrete::f() // Abstract2 a2; // Error: abstract class (final overrider of g() is pure) }
重新声明纯虚方法有什么目的吗?
在派生类Abstract2中将虚方法声明为纯方法是有目的的:g即使在Concrete.
这会改变语义吗?即 B::foo 隐藏 A::foo 并引入新的 vftable 吗?
不。
如果 A::foo 实际上不是纯虚拟的但提供了一个实现(仍然为我编译),那么在上面的例子中会发生什么?
请参阅示例。
您不必像virtual在派生类中那样对方法进行 delcare 。当它virtual在基virtual类中声明时,它也在派生类中。简而言之, the=0只是告诉编译器不一定有定义,并且该类是抽象的。您的示例与以下示例相同:
struct AA { // abstract
virtual void foo() = 0;
};
struct BB : public AA { }; // abstract
struct CC : public BB { // concrete
void foo() override {}
};
Run Code Online (Sandbox Code Playgroud)
我知道的唯一区别是类型BB::foo:
// above
std::cout << std::is_same< decltype(&BB::foo), void (AA::*)()>::value;
std::cout << std::is_same< decltype(&BB::foo), void (BB::*)()>::value;
std::cout << std::is_same< decltype(&BB::foo), void (CC::*)()>::value << "\n";
// your example
std::cout << std::is_same< decltype(&B::foo), void (A::*)()>::value;
std::cout << std::is_same< decltype(&B::foo), void (B::*)()>::value;
std::cout << std::is_same< decltype(&B::foo), void (C::*)()>::value << "\n";
Run Code Online (Sandbox Code Playgroud)
输出是:
100
010
Run Code Online (Sandbox Code Playgroud)
也就是说,重新声明foo的B名称介绍foo直接B。B::foo是 的成员函数B。另一方面,在我的示例中BB::foo是来自AA. 但是,这并不影响C::foo.
| 归档时间: |
|
| 查看次数: |
201 次 |
| 最近记录: |