问题
为什么不尝试虚拟继承,如果它似乎解决了我的钻石继承问题?
简报:
在学习C ++时,我遇到了以下代码的一些编译器错误:
#include <stdlib.h>
#include <iostream>
class IFoo{
public:
virtual void Hello() = 0;
};
class Foo : public IFoo{
public:
void Hello()
{
printf("Hello");
}
};
class IBar : public IFoo{
public:
virtual void HelloWorld() = 0;
};
class Bar : public IBar, public Foo{
public:
void HelloWorld()
{
Hello();
printf("World");
}
};
int main()
{
Bar b;
b.HelloWorld();
system("pause");
return 0;
}
我希望Bar实现抽象类IBar,它将IFoo作为基类,但后来我想要由Bar的第二个基类Foo提供的所有IFoo实现。
我得到2个编译器错误(GCC 4.9.2):一个与歧义有关,另一个与抽象类IFoo缺少实现有关。
然后我找到了this question并且满足了虚拟继承的概念,这导致我this page。在本教程之后,我添加了虚拟继承,所有问题都消失了:
class Foo : public virtual IFoo{...
class IBar : public virtual IFoo{...
但是question中的用户建议不要尝试虚拟继承。因此我的问题。
答案 0 :(得分:0)
Hello()
中的Bar::HelloWorld()
来电是不明确的。编译器无法判断您是否尝试从Hello()
或IBar
拨打Foo
。您可以在其中调用Foo::Hello()
或IBar::Hello()
。话虽如此,你的继承结构并没有多大意义。
您的Bar
课程还需要覆盖从Hello
继承的IBar
。
如果你有c ++ 11,最好用override
关键字标记你要覆盖的虚拟函数:
#include <stdlib.h>
#include <iostream>
class IFoo{
public:
virtual void Hello() = 0;
};
class Foo : public IFoo{
public:
virtual void Hello() override
{
printf("Hello");
}
};
class IBar : public IFoo{
public:
virtual void HelloWorld() = 0;
};
class Bar : public IBar, public Foo{
public:
virtual void HelloWorld() override
{
Foo::Hello();
printf("World");
}
void Hello() override {}
};
int main()
{
Bar b;
b.HelloWorld();
system("pause");
return 0;
}
要回答关于虚拟继承的问题,您可以轻松地将继承结构更改为仍可以避免菱形图案的工作。很少需要钻石图案,通常可以避免:
#include <stdlib.h>
#include <iostream>
class IFoo{
public:
virtual void Hello() = 0;
};
class Foo : public IFoo{
public:
virtual void Hello() override
{
printf("Hello");
}
};
class IBar {
public:
virtual void World() = 0;
};
class Bar : public IBar{
public:
virtual void World() override
{
printf("World");
}
};
class FooBar : public Foo, public Bar
{
public:
virtual void HelloWorld()
{
Hello();
World();
}
};
int main()
{
FooBar b;
b.HelloWorld();
system("pause");
return 0;
}
答案 1 :(得分:0)
你的班级
Bar
必须覆盖
Hello
否则类Bar也变得纯粹抽象,因为
Hello
从
继承IFoo.
每当一个类继承一个abtract基类时,它必须实现所有基类&#39;纯虚函数,否则派生类本身也变得抽象。
class Base{
public:
virtual void foo() = 0;
};
// this class is abstract, it doesn't implement Base::foo
class Derived1 : public Base{
public:
void fooDerived() {}
};
// this class is not abstract, it implements Base::foo
class Derived2 : public Base{
public:
void foo() {}
};
正如另一个答案中所建议的,在C ++ 11中,您可以使用override关键字声明该函数,这可以确保该函数覆盖虚拟函数。像这样:
// this class is not abstract, it implements Base::foo
class Derived2 : public Base{
public:
void foo() override {}
};
虚拟继承解决了另一个问题,即从多个声明相同函数或成员的基类继承时出现歧义问题。