c++抽象类在另一个基类中的实现
c++ abstract class implementation in another base class
问题
如果虚拟继承似乎可以解决我下面的钻石继承问题,为什么不尝试呢?
简报:
在学习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实现以IFoo为基类的抽象类IBar,但我希望Bar的第二个基类Foo提供IFoo的所有实现。
我得到了两个编译器错误(GCC 4.9.2):一个与歧义有关,另一个与抽象类IFoo的实现缺失有关。
然后我发现了这个问题,并遇到了虚拟继承的概念,这将我带到了这一页。在教程之后,我添加了虚拟继承,所有问题都消失了:
class Foo : public virtual IFoo{...
class IBar : public virtual IFoo{...
但有问题的用户建议不要尝试虚拟继承。因此,我提出了这个问题。
您的班级
Bar
必须覆盖
Hello
否则类Bar也会变得纯粹抽象,因为
Hello
一直从继承
IFoo.
每当一个类继承abtract基类时,它必须实现基类的所有纯虚拟函数,否则派生类本身也会变得抽象。
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 {}
};
虚拟继承解决了另一个问题,即从多个声明相同函数或成员的基类继承时的模糊性问题。
Bar::HelloWorld()
中的Hello()
调用不明确。编译器无法判断您是试图从IBar
还是Foo
调用Hello()
。您可以在它的位置调用Foo::Hello()
或IBar::Hello()
。话虽如此,你的继承结构并没有真正意义。
Bar
类还需要重写它从IBar
继承的Hello
。
如果您有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;
}
- 如何正确实现与基类不同的版本?
- 可以具有不同基成员实现的类的最佳实现
- 对派生自同一基类的类实现冲突检查
- 无法使用在子类中定义的虚拟getter实现基类
- 关于C++从派生类调用在基类中实现的虚拟函数的问题
- 如何在基类中定义静态接口,并确保该接口必须在派生类中实现
- 如何在CRTP实现中传递基类指针
- 有没有一种方法可以使用SFINAE来检测一个类型是否实现了给定的抽象基类
- C++ 多重继承:使用基类 A 的实现实现基类 B 的抽象方法
- 如何在子类中重写时调用私有虚拟基类实现
- 如何在基类中实现子类迭代器的统一接口?
- 调用基类克隆实现
- 检查实现哪些基类
- 我如何实现从其基类获取变量的构造函数
- 什么更有效率?在重载函数中或通过在基类函数中检查对象类型来实现
- 如何在抽象基类中实现运算符+
- 将多态性与运算符 + 重载模板化类结合使用.如何实现基类?
- 如何私下从基类的导数继承,但实现基类的公共接口?
- 从派生类实现基类构造函数专用化的替代方法是什么
- 实现基类方法来访问派生类的属性