C++在基类本身中重写基类的抽象方法

C++ overriding abstract method of Base class in the base class itself?

本文关键字:基类 重写 抽象方法 C++      更新时间:2023-10-16

如果我有一个基类,那么:

class Base {
public:
Base(){}
virtual void foo()=0;
};

现在,如果我从基类派生任何类,它将不得不重写foo()

如果我也想要基类在foo()上的行为呢?所以这个基类有自己的foo,除此之外,它的每一个都必须重写foo?这可能吗?

如果您执行以下操作:

class Base {
public:
Base(){}
virtual void foo() = 0;
};
void Base::foo() {
{ 
cout << "Hello";
}

您将获得一个抽象类,因此您将不能创建基类的对象b,并通过调用b.foo()使其使用您的foo(()实现。

所以这不是你想要的!下一个问题是,如果你不能使用Base::foo,为什么允许你提供它的实现。好吧,实际上你可以!但不是直接的。

class Deriv : public Base {
public:
Deriv(){}
virtual void foo();
};
void Deriv::foo() 
{ 
Base::foo(); cout << "  world!";
}

正如您所看到的,Base::foo()可以被派生类使用。

回到你的问题上来。答案是可以完全按照您指定的操作,除了基类是抽象的。

另一种选择是按照大多数人的做法,当您在Base中为foo()提供实现时,不要指定=0。这意味着派生类可以覆盖foo(),但没有覆盖。在我看来,这实际上是完全合理的:在Base::foo()的默认实现有意义的派生类中,你可以保留它,但对于那些需要不同东西的类,你可以覆盖它。

更新:我试图提出一个实际需要问题的场景,并提出了这个:

假设Document及其派生类表示文档类型,并且Document包含一个虚拟方法getClassIcon(),该方法返回表示文档类型的图标的图像文件的URL。Document有一个图标(表示通用文档的东西)是有意义的,要求所有派生类重写getClassIcon()以提供自己的图标也是有意义的。

话虽如此,在这个特定的例子中,似乎很容易找到另一种设计:使Document::getClassIcon()成为一个纯虚拟方法(=0)(使Document成为一个抽象类),并将OtherDocument添加为其派生类之一,从而实现之前的getClassIconDocument。PDFDocument、MSWordDocument等都需要根据需要重写getClassIcon()。这种重新设计可能会揭示的是,以前的设计(由C++的想象版本支持,该版本允许问题的要求)将基类Document的角色和代表不属于任何已知类型的文档的类OtherDocument的角色混为一谈。当然,这一切都在旁观者的眼中:-)有人可能会说,第二个设计只是因为语言中缺少功能而变得必要。我想我们(在很大程度上)是根据我们所说的(计算机)语言来思考的

您可以为纯虚拟方法提供一个实现:

class Base {
...
virtual void foo()=0;
}
void Base::foo() {
... implementation goes here ...
}

这个类仍然是抽象的。如果你不想让它抽象,你必须删除=0。但是,一旦这样做,就不能强制派生类提供它们自己的实现。

换句话说,你必须做出选择。