C++ 中的继承:在父子类中定义变量
Posted
技术标签:
【中文标题】C++ 中的继承:在父子类中定义变量【英文标题】:Inheritance in C++: define variables in parent-child classes 【发布时间】:2019-05-03 11:47:46 【问题描述】:问题
我正在寻找在父子类中定义变量的最佳方法,以便通过指向其父类的指针调用。 这是协议代码:
class Base
public:
virtual void function() = 0;
;
class A : public Base
public:
int a, b;
A(int a_, int b_) : a(a_), b(b_) ;
void function() // do something..
;
class B : public Base
public:
int a, b;
B(int a_, int b_) : a(a_), b(b_) ;
void function() // do something..
;
Base* elements[2] =
new A(1,2),
new B(3,4)
;
由于我在两个构造函数中都定义了a, b
,我可以在抽象类Base
中定义它们。这样代码应该更高效、更干净。这种做法正确吗?我应该如何定义它们?
可能的解决方案
我想到的解决方案是实现一个函数,例如返回 a
,如下所示:
class Base
public:
virtual int return_a() = 0;
;
class A : public Base
public:
int a, b;
A(int a_, int b_) : a(a_), b(b_) ;
int return_a()
return a;
;
int main()
int a = elements[0]->return_a();
这可行,但我确信这不是一种有效的方法。在抽象类中定义a, b
更好吗?谢谢
【问题讨论】:
如果Base
的所有 个子级具有这些a
和b
成员,那么在Base
类中定义它们似乎是一个自然的解决方案。如果只有 一些 孩子使用 a
和 b
,那么您可以添加一个中间类,例如struct SubBase : public Base int a; int b; ;
然后让你的 A
和 B
类继承自该类。
由于您显示的所有成员都是公开的,因此您可以改用struct
(与class
相同,但默认可见性为public
而不是private
)。如果a
和b
成员是公开的,则您不需要为它们提供任何“getter”函数。
公共派生方法可以直接访问公共 Base 属性。不需要'Base::return_x()'。
【参考方案1】:
这种做法正确吗?
我认为这正在变成基于意见的问答。如果您的所有派生类都必须包含成员a
和b
,那么在我看来,它们应该是基类的一部分。这样,您可以保证您的所有派生类都将包含成员 a
和 b
,并且您(或其他人)不会冒忘记包含它们的风险。此外,通过在基类中包含成员,您不必在每个派生类中都包含它们,从而节省了内存。 C++ 的virtual
为您提供了完成多态性所需的所有工具,这就是您创建Base *
数组时发生的情况。
我还建议您将关键字override
用于派生类中被覆盖的虚函数,将关键字final
用于不打算成为基类的派生类。您可以从 Scott Meyers Modern C++ 一书中了解使用这些关键字的好处。
struct Base
int a, b;
Base(int a_, int b_) : a(a_) , b(b_)
;
virtual void function() = 0;
;
struct A : Base // A can be a base class of another class.
A(int a_, int b_) : Base(a_,b_)
;
void funtion() // this will compile, but it's not going to override the Base::function()
;
;
struct B final : Base // B can never become a base class.
B(int a_, int b_) : Base(a_,b_)
;
void funtion() override // this won't compile because override will see that we mis-spelled function()
;
;
但是,没有 C++ 规则禁止您在所有派生类中包含成员。
另外,如果您的所有成员都是public
,那么您可以使用struct
来避免在类和继承方法中键入public
。
struct Base
// all members are public
;
struct Derived : Base // public inheritance by default.
// all members are public
;
【讨论】:
感谢您的完整回答。在这种情况下,我想知道考虑到效率的解决方案(正如您所说,您的解决方案可以节省内存),但是如果我想问一个基于意见的问题,我可以在哪里做呢? @maurocomi:没问题!同样,这是一个灰色地带。您的 OP 中的代码运行良好。没有错误,也没有包含非法指令。这纯粹是一个效率问题。然而,效率可能会因软件的需求而异,因此没有一种正确的解决方案。这就是将您的问题变成基于意见的问答的原因。但是话又说回来,我认为您的问题对 SO 有效,因为必须考虑 IS-A、HAS-A、动态多态性等之间的差异。也许code-review 下次更适合。【参考方案2】:这有点基于意见,但这是我根据您发布的代码的想法。
由于您已将Base
(所有类都派生自该类)设为抽象类,因此您似乎想将其用作接口。
在这种情况下,最好区分接口继承和实现继承。让Base
没有任何数据,这意味着它不需要任何构造函数。
这是 Bjarne Stroustrup 给出的编码指南之一,标题为:When designing a class hierarchy, distinguish between implementation inheritance and interface inheritance
。
给出的原因是:
接口中的实现细节使接口变得脆弱;也就是说,使其用户很容易在实现更改后不得不重新编译。基类中的数据会增加实现基类的复杂性,并可能导致代码复制。
请注意,如果派生类中的数据为 public
,则不需要 getter 或 setter。
【讨论】:
以上是关于C++ 中的继承:在父子类中定义变量的主要内容,如果未能解决你的问题,请参考以下文章