为什么不从不同的继承分支覆盖纯虚方法?
Why are pure virtual methods not overridden from a different inheritance branch?
我有这个,可能有点复杂class层次结构:
class BS {
public:
virtual void meth()=0;
};
class BCA : public virtual BS {
};
class BSS : public virtual BS {
};
class BCS : public virtual BCA, public virtual BSS {
};
class BI4 {
public:
void meth() {};
};
class BT4 : public virtual BI4, public virtual BSS {
};
class T4 : public virtual BCS, public virtual BT4 {
};
int main() {
T4 t4;
};
现在的问题是,尽管 void meth()
在继承图中可用,尽管这段代码无法编译:
$ g++ -c t.cc -std=c++11
t.cc: In function ‘int main()’:
t.cc:27:6: error: cannot declare variable ‘t4’ to be of abstract type ‘T4’
T4 t4;
^
t.cc:23:7: note: because the following virtual functions are pure within ‘T4’:
class T4 : public virtual BCS, public virtual BT4 {
^
t.cc:3:18: note: virtual void BS::meth()
virtual void meth()=0;
^
t.cc:3:18: note: virtual void BS::meth()
在我看来,好像 BS
无法通过 BS->BCA->BCS->T4->BT4->BI4 链看到重载的 meth()
方法。
但为什么?方法一目了然,C++用的C3线性化算法应该能很清楚的找到。
BI4
不直接或间接继承自 BS
,因此它的方法 BI4::meth()
完全不相关,不能覆盖 BS::meth()
.
您只能覆盖基础 类 的方法,而不能覆盖 "sibling" 或 "uncle" 类.
的方法
语言规则不允许。虚函数只能通过在派生 class 中声明具有相同名称和参数的函数来覆盖。由于 BI4
不是从 BS
派生的,因此 BI4::meth
无法覆盖 BS::meth
。如果 class 从 BS
和 BI4
继承(直接或间接),那么它会继承 两个 称为 meth
的函数:一个来自 BS
,仍然抽象且未被覆盖,其中一个来自 BI4
.
主要有两个方面:
- 给定的 class 只能覆盖其基础 classes 的成员函数。
由于您的 BI4
class 没有 BS
作为基础 class,它无法覆盖 BS
. 的任何内容
- 可以继承在虚基 class 中定义的纯虚函数的实现,就像在 Java 中一样,但是 class 提供该实现本身也必须具有该虚拟基础 class.
示例:
struct Base
{
virtual void foo() = 0;
};
#ifdef GOOD
struct Impl_foo: virtual Base
{
void foo() override {}
};
#else
struct Impl_foo
{
virtual void foo() {}
};
#endif
struct Abstract_derived: virtual Base
{};
struct Derived
: Abstract_derived
, Impl_foo // Java-like implementation inheritance.
// In C++ called "by dominance".
{};
auto main()
-> int
{
Derived o;
o.foo();
}
没有定义 GOOD
宏符号,此代码无法编译。
我有这个,可能有点复杂class层次结构:
class BS {
public:
virtual void meth()=0;
};
class BCA : public virtual BS {
};
class BSS : public virtual BS {
};
class BCS : public virtual BCA, public virtual BSS {
};
class BI4 {
public:
void meth() {};
};
class BT4 : public virtual BI4, public virtual BSS {
};
class T4 : public virtual BCS, public virtual BT4 {
};
int main() {
T4 t4;
};
现在的问题是,尽管 void meth()
在继承图中可用,尽管这段代码无法编译:
$ g++ -c t.cc -std=c++11
t.cc: In function ‘int main()’:
t.cc:27:6: error: cannot declare variable ‘t4’ to be of abstract type ‘T4’
T4 t4;
^
t.cc:23:7: note: because the following virtual functions are pure within ‘T4’:
class T4 : public virtual BCS, public virtual BT4 {
^
t.cc:3:18: note: virtual void BS::meth()
virtual void meth()=0;
^
t.cc:3:18: note: virtual void BS::meth()
在我看来,好像 BS
无法通过 BS->BCA->BCS->T4->BT4->BI4 链看到重载的 meth()
方法。
但为什么?方法一目了然,C++用的C3线性化算法应该能很清楚的找到。
BI4
不直接或间接继承自 BS
,因此它的方法 BI4::meth()
完全不相关,不能覆盖 BS::meth()
.
您只能覆盖基础 类 的方法,而不能覆盖 "sibling" 或 "uncle" 类.
的方法语言规则不允许。虚函数只能通过在派生 class 中声明具有相同名称和参数的函数来覆盖。由于 BI4
不是从 BS
派生的,因此 BI4::meth
无法覆盖 BS::meth
。如果 class 从 BS
和 BI4
继承(直接或间接),那么它会继承 两个 称为 meth
的函数:一个来自 BS
,仍然抽象且未被覆盖,其中一个来自 BI4
.
主要有两个方面:
- 给定的 class 只能覆盖其基础 classes 的成员函数。
由于您的BI4
class 没有BS
作为基础 class,它无法覆盖BS
. 的任何内容
- 可以继承在虚基 class 中定义的纯虚函数的实现,就像在 Java 中一样,但是 class 提供该实现本身也必须具有该虚拟基础 class.
示例:
struct Base
{
virtual void foo() = 0;
};
#ifdef GOOD
struct Impl_foo: virtual Base
{
void foo() override {}
};
#else
struct Impl_foo
{
virtual void foo() {}
};
#endif
struct Abstract_derived: virtual Base
{};
struct Derived
: Abstract_derived
, Impl_foo // Java-like implementation inheritance.
// In C++ called "by dominance".
{};
auto main()
-> int
{
Derived o;
o.foo();
}
没有定义 GOOD
宏符号,此代码无法编译。