如何防止派生 class 在 C++ 中成为抽象 class?
How to prevent a derived class being an abstract class in c++?
我有一个关于多态性的问题。以下示例将导致错误 "cannot declare variable ‘obj’ to be of abstract type ‘B’"
我知道问题出在函数 A::foo() 的纯虚方法上,它使 A 成为抽象的 class。此外,class B 是 class A 固有的。如果我没有在 B 的主体中实现方法 foo(),那是否也必然使 B 成为抽象对象?从而导致错误?但这是什么逻辑?可能有很多其他派生的 classes 来自我的基础 class A,函数 foo 可能适用于某些派生的 class,但对于 Class B 可能完全没用. 当然,我可以声明一个空函数 B::foo(),它什么都不做,并使代码成为 运行。但是,对于这种行为有更好的解决方案或解释吗?谢谢!
struct A
{
A() : x(0) {}
virtual int foo() const = 0; // if I remove this line, code will run with no problem.
int x;
};
struct B : A {};
int main()
{
B obj;
cout << obj.x << endl;
return 0;
}
Class A
是抽象的,因为 foo()=0
。
如果您从 A
派生,则需要实现此 foo()
,否则派生的 class 仍然是抽象的。
所以 class B
必须
int foo() const override {}
能够作为物件使用
您可以将此函数声明为私有的,使其无法访问...但问题是如果 foo()
是否实现 foo()
为什么 B
派生自 A
.也许您需要重新考虑您的设计。也许应该将 foo()=0
移动到一个单独的接口 class,并实现多重继承。
Class C : public A, public FooInterface {
public:
int foo() const override {};
};
或者,您可以实现派生自 A
但添加 foo()
的 AwithFoo
class。 IE。添加一些层次结构。
class A {}
class B : public A {}
class AwithFoo : public A {
public:
using A::A; // a way to inherit the constructor.
virtual int foo() const = 0;
}
class C : public AwithFoo {
public:
int foo() const override {};
}
尽管后一种解决方案并不总是好的解决方案。它将添加额外的间接层。
您不应依赖 classed 为您提供不需要的功能。如果你这样做,你就违反了 liskov substitution principle. That`s a bad design and will lead you to many problems such as refused bequest。
但是,如果您需要该功能并从基础 class 继承,您必须实现该功能或将其保留为抽象,这将使派生的 class 也抽象。
首先,你是对的,不在 A
中实现 foo
使 A
抽象,不在 B
中实现 foo
使那个抽象还有。
多态的全部意义就是你为一组类提供一个通用的接口。任何派生类型一般都可以作为基本类型,具体行为只会在细节上有所不同(例如,像汽车、自行车或轮船的转向,机制不同,但你 可以 引导他们所有人)。
如果在B
上调用foo
没有意义,那么先问'Why?'!不知何故,B
不可能是真正的 A
那么,就像螺丝刀不能是锤子一样(但两者都可以是工具)。
如果您遇到这样的麻烦,那么很可能是您的设计存在缺陷。
我有一个关于多态性的问题。以下示例将导致错误 "cannot declare variable ‘obj’ to be of abstract type ‘B’"
我知道问题出在函数 A::foo() 的纯虚方法上,它使 A 成为抽象的 class。此外,class B 是 class A 固有的。如果我没有在 B 的主体中实现方法 foo(),那是否也必然使 B 成为抽象对象?从而导致错误?但这是什么逻辑?可能有很多其他派生的 classes 来自我的基础 class A,函数 foo 可能适用于某些派生的 class,但对于 Class B 可能完全没用. 当然,我可以声明一个空函数 B::foo(),它什么都不做,并使代码成为 运行。但是,对于这种行为有更好的解决方案或解释吗?谢谢!
struct A
{
A() : x(0) {}
virtual int foo() const = 0; // if I remove this line, code will run with no problem.
int x;
};
struct B : A {};
int main()
{
B obj;
cout << obj.x << endl;
return 0;
}
Class A
是抽象的,因为 foo()=0
。
如果您从 A
派生,则需要实现此 foo()
,否则派生的 class 仍然是抽象的。
所以 class B
必须
int foo() const override {}
能够作为物件使用
您可以将此函数声明为私有的,使其无法访问...但问题是如果 foo()
是否实现 foo()
为什么 B
派生自 A
.也许您需要重新考虑您的设计。也许应该将 foo()=0
移动到一个单独的接口 class,并实现多重继承。
Class C : public A, public FooInterface {
public:
int foo() const override {};
};
或者,您可以实现派生自 A
但添加 foo()
的 AwithFoo
class。 IE。添加一些层次结构。
class A {}
class B : public A {}
class AwithFoo : public A {
public:
using A::A; // a way to inherit the constructor.
virtual int foo() const = 0;
}
class C : public AwithFoo {
public:
int foo() const override {};
}
尽管后一种解决方案并不总是好的解决方案。它将添加额外的间接层。
您不应依赖 classed 为您提供不需要的功能。如果你这样做,你就违反了 liskov substitution principle. That`s a bad design and will lead you to many problems such as refused bequest。
但是,如果您需要该功能并从基础 class 继承,您必须实现该功能或将其保留为抽象,这将使派生的 class 也抽象。
首先,你是对的,不在 A
中实现 foo
使 A
抽象,不在 B
中实现 foo
使那个抽象还有。
多态的全部意义就是你为一组类提供一个通用的接口。任何派生类型一般都可以作为基本类型,具体行为只会在细节上有所不同(例如,像汽车、自行车或轮船的转向,机制不同,但你 可以 引导他们所有人)。
如果在B
上调用foo
没有意义,那么先问'Why?'!不知何故,B
不可能是真正的 A
那么,就像螺丝刀不能是锤子一样(但两者都可以是工具)。
如果您遇到这样的麻烦,那么很可能是您的设计存在缺陷。