我想知道什么是“虚拟基类”以及它的含义。
让我举个例子:
class Foo
{
public:
void DoSomething() { /* ... */ }
};
class Bar : public virtual Foo
{
public:
void DoSpecific() { /* ... */ }
};
我想知道什么是“虚拟基类”以及它的含义。
让我举个例子:
class Foo
{
public:
void DoSomething() { /* ... */ }
};
class Bar : public virtual Foo
{
public:
void DoSpecific() { /* ... */ }
};
当前回答
虚拟基类用于虚拟继承,是一种使用多重继承时防止在继承层次结构中出现给定类的多个“实例”的方法。
考虑以下场景:
class A { public: void Foo() {} };
class B : public A {};
class C : public A {};
class D : public B, public C {};
上面的类层次结构导致了“可怕的钻石”,看起来像这样:
A
/ \
B C
\ /
D
D的一个实例将由B和C组成,B包含A, C也包含A。所以你有两个A的“实例”(为了更好的表达)。
在这种情况下,就有可能出现模棱两可的情况。当你这样做时会发生什么:
D d;
d.Foo(); // is this B's Foo() or C's Foo() ??
虚拟继承可以解决这个问题。当您在继承类时指定virtual时,您是在告诉编译器您只需要一个实例。
class A { public: void Foo() {} };
class B : public virtual A {};
class C : public virtual A {};
class D : public B, public C {};
这意味着在层次结构中只包含A的一个“实例”。因此
D d;
d.Foo(); // no longer ambiguous
这是一个小总结。要了解更多信息,请阅读这个和这个。这里还有一个很好的例子。
其他回答
虚拟类与虚拟继承不同。虚拟类你不能实例化,虚拟继承完全是另一回事。
维基百科描述得比我好。http://en.wikipedia.org/wiki/Virtual_inheritance
虚拟基类用于虚拟继承,是一种使用多重继承时防止在继承层次结构中出现给定类的多个“实例”的方法。
考虑以下场景:
class A { public: void Foo() {} };
class B : public A {};
class C : public A {};
class D : public B, public C {};
上面的类层次结构导致了“可怕的钻石”,看起来像这样:
A
/ \
B C
\ /
D
D的一个实例将由B和C组成,B包含A, C也包含A。所以你有两个A的“实例”(为了更好的表达)。
在这种情况下,就有可能出现模棱两可的情况。当你这样做时会发生什么:
D d;
d.Foo(); // is this B's Foo() or C's Foo() ??
虚拟继承可以解决这个问题。当您在继承类时指定virtual时,您是在告诉编译器您只需要一个实例。
class A { public: void Foo() {} };
class B : public virtual A {};
class C : public virtual A {};
class D : public B, public C {};
这意味着在层次结构中只包含A的一个“实例”。因此
D d;
d.Foo(); // no longer ambiguous
这是一个小总结。要了解更多信息,请阅读这个和这个。这里还有一个很好的例子。
这意味着对虚函数的调用将被转发到“正确的”类。
C+ FAQ上升。
简而言之,它通常用于多继承场景,其中形成了“菱形”层次结构。虚继承将打破在底层类中创建的模糊性,当您调用该类中的函数并且函数需要解析到底层类之上的类D1或D2时。有关图表和详细信息,请参阅FAQ项。
它还用于姐妹委托,这是一个强大的功能(尽管不适合心脏薄弱的人)。请看这个FAQ。
参见Effective c++第3版中的第40项(第2版中的43项)。
除了前面提到的多重继承和虚拟继承之外,在Dr Dobb's Journal上还有一篇非常有趣的文章:多重继承被认为是有用的
你有点让人困惑了。我不知道你是否混淆了一些概念。
op中没有虚基类,只有基类。
你做了虚拟继承。这通常用于多重继承,以便多个派生类使用基类的成员而不复制它们。
不实例化具有纯虚函数的基类。这需要Paul掌握的语法。通常使用它是为了派生类必须定义这些函数。
我不想再解释了,因为我不太明白你在问什么。