如果我有这样的基类:
class Base {
public:
Base(){}
virtual void foo()=0;
};
现在,如果我从Base类中派生出任何类,则必须覆盖foo()
。
如果我想在基础类的foo()
上进行行为怎么办?所以基类有它自己的foo
,除此之外,它的每一个都必须覆盖foo
?这可能吗?
答案 0 :(得分:6)
如果您执行以下操作:
class Base {
public:
Base(){}
virtual void foo() = 0;
};
void Base::foo() {
{
cout << "Hello";
}
你将得到一个抽象类,所以你不能够创建类Base的对象b并让它通过调用b.foo()来使用你的foo()实现。< / p>
所以这不是你想要的!接下来的问题是,如果您不能使用它,为什么允许您为Base :: foo提供实现。嗯,实际上你可以!不是直接的。
class Deriv : public Base {
public:
Deriv(){}
virtual void foo();
};
void Deriv::foo()
{
Base::foo(); cout << " world!";
}
正如您所见,派生类可以使用Base :: foo() 。
回到你的问题。答案是你可以完全按照你指定的方式完成,除了Base类是抽象的。
替代方法是执行大多数人所做的事情,而不是在Base中为foo()提供实现时指定= 0。这意味着派生类可以覆盖foo()但不具有。这在我看来实际上是完全合理的:在Base :: foo()的默认实现有意义的派生类中,你保留它,但对于那些需要不同的东西,你可以覆盖它。
更新:我试图提出一个实际需要问题的方案,并提出了这个问题:
想象一下,Document及其派生类表示文档类型,Document包含一个虚拟方法getClassIcon(),返回代表文档类型的图标的图像文件的URL。 Document有一个图标(表示通用文档的东西)是有意义的,并且要求所有派生类重写getClassIcon()以提供自己的图标也是有意义的。
话虽如此,在这个特定的例子中,似乎很容易找到另一种设计:使Document :: getClassIcon()成为一个纯虚方法(= 0)(使Document成为一个抽象类)并添加OtherDocument作为其派生之一类,给它以前的getClassIcon文件的实现。 PDFDocument,MSWordDocument等都需要根据需要覆盖getClassIcon()。这个重新设计可能需要揭示的是,之前的设计(由一个假想的C ++版本支持,允许问题所要求的)已经混淆了基类,Document和类的作用。对于不属于任何已知类型的文档,OtherDocument。当然,这一切都在旁观者的眼中:-)有人可能会争辩说第二种设计仅仅是必要的,因为语言缺少功能。我想我们(在很大程度上)根据我们所说的(计算机)语言来思考。 : - )
答案 1 :(得分:3)
您可以为纯虚方法提供实现:
class Base {
...
virtual void foo()=0;
}
void Base::foo() {
... implementation goes here ...
}
班级仍然是抽象的。如果您不希望它是抽象的,则必须删除=0
。但是,一旦这样做,就无法强制派生类提供自己的实现。
换句话说,你必须做出选择。