假设我们有
class A {
public:
virtual int foo() { cout << "foo!"; }
}
class B : public A {
public:
virtual int foo() =0;
}
class C : public B {
public:
virtual int foo() { cout << "moo!"; }
}
这真的覆盖吗?我认为这实际上是重载。 制作这样的东西,设计明智是什么意思?
我们得到了一个基类A.然后我们得到了一个抽象派生类B,它派生自具体类A,然后通过C实现B。
我们在这做什么,是否有意义?
答案 0 :(得分:3)
重载意味着您有两个相同名称但具有不同参数的函数。情况并非如此。
示例:
int functionA() { /*...*/ };
int functionA(int someParameter) { /*...*/ };
重写意味着在子类中重写具有相同参数的函数。这就是你作为一个例子。
这是定义部分。现在进行设计:
当你有一个纯虚函数时,具体的子类必须覆盖它。因此,通过添加纯虚函数,可以确保所有子类都提供相同的函数集(= interface)。这似乎是示例代码中的情况。
但这不是一个很好的例子,因为具体的超类已经实现了foo()的默认功能。当有一个抽象子类将它重新定义为纯虚拟时,对我来说这是一个标志,类层次结构是有缺陷的,因为子类(以及foo()的调用者)通常应该能够回退到默认实现。用这样一个抽象的例子解释起来有点难,但是这样的层次结构对我来说有点怀疑。
答案 1 :(得分:1)
在我看来,纯虚方法的唯一效果就是使B成为一个抽象类。
答案 2 :(得分:1)
它仍然是重写的,因为当你有p
类型的指针A*
到类C
的实例时,p->foo()
仍会调用C::foo()
可能,设计人员希望在层次结构中插入一个抽象类,该抽象类派生自某个具体类,并强制覆盖子类中的方法。我不认为这是非常明智的。
答案 3 :(得分:1)
你说从B派生的类必须实现 int foo(); 。您可能想要做这样的事情来迫使其他程序员考虑他们希望 foo()的行为,但我认为这是一个坏主意 - 实际上他们可能通过调用< EM> A :: foo的()
如果你只想让 B 抽象,给它一个纯虚拟析构函数 - 你还需要提供一个析构函数的实现,以避免链接错误。