4

如果我有这样的基类:

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

现在,如果我从 Base 类派生出任何类,它将不得不覆盖foo().

如果我也想要foo()Base 类的行为怎么办?所以这个基类有它自己的foo,最重要的是,它的每一个都必须覆盖foo?那可能吗?

4

2 回答 2

6

如果您执行以下操作:

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

您将获得一个抽象类,因此您将无法创建 Base 类的对象 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 类将是抽象的。

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

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

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

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

于 2012-11-27T21:09:30.257 回答
3

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

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

void Base::foo() {
     ... implementation goes here ...
}

该类仍然是抽象的。如果您不希望它抽象,则必须删除=0. 但是,一旦这样做,就不能强制派生类提供它们自己的实现。

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

于 2012-11-27T20:21:59.527 回答