C++ 中的继承:在父子关系中定义变量 类
Inheritance in C++: define variables in parent-child classes
问题
我正在寻找在父子 classes 中定义变量的最佳方法,以便通过指向其父 class 的指针进行调用。
这是原代码:
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
,所以我可能会在抽象中定义它们 class Base
。这样代码应该更高效和干净。这种做法是否正确?我应该如何定义它们?
可能的解决方案
我想到的解决方案是实现一个函数 returns 例如 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();
}
这可行,但我确信这不是一种有效的方法。在摘要class中定义a, b
是不是更好?谢谢
Is this practice correct?
我认为这正在变成一个基于意见的问答。如果所有派生的 classes 都必须包含成员 a
和 b
, 那么在我看来,它们应该是基础 [=] 的一部分34=]。这样,您可以保证所有派生的 classes 都将包含成员 a
和 b
,并且您(或其他人)不会 运行 忘记的风险包括他们。此外,通过将成员包含在基 class 中,您不必在每个派生 class 中都包含它们,从而节省了内存。 C++ 的 virtual
为您提供了实现多态性的所有必要工具,当您创建一个 Base *
.
的数组时就会发生这种情况
我还建议您对派生 class 中覆盖的虚函数使用关键字 override
,对派生 class 使用关键字 final
es 不打算成为基础 classes。您可以从 Scott Meyers 现代 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++ 规则禁止您在所有派生的 classes 中包含成员。
此外,如果您的所有成员都是 public
,那么您可以使用 struct
来避免在 classes 和继承中键入 public
方法。
struct Base
{
// all members are public
};
struct Derived : Base // public inheritance by default.
{
// all members are public
};
这有点基于意见,但这是我根据您发布的代码得出的想法。
由于您已将 Base
(所有 classes 均从中派生)抽象为 class,看来您想将其用作接口。
那样的话,还是分清接口继承和实现继承比较好。让 Base
没有任何数据,这意味着它不需要任何构造函数。
这是 Bjarne Stroustrup 给出的编码指南之一,标题为:When designing a class hierarchy, distinguish between implementation inheritance and interface inheritance
。
给出的原因是:
Implementation details in an interface make the interface brittle; that is, make its users vulnerable to having to recompile after changes in the implementation. Data in a base class increases the complexity of implementing the base and can lead to replication of code.
请注意,如果派生的 classes 中的数据是 public
。
,则不需要 getter 或 setter
问题
我正在寻找在父子 classes 中定义变量的最佳方法,以便通过指向其父 class 的指针进行调用。
这是原代码:
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
,所以我可能会在抽象中定义它们 class Base
。这样代码应该更高效和干净。这种做法是否正确?我应该如何定义它们?
可能的解决方案
我想到的解决方案是实现一个函数 returns 例如 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();
}
这可行,但我确信这不是一种有效的方法。在摘要class中定义a, b
是不是更好?谢谢
Is this practice correct?
我认为这正在变成一个基于意见的问答。如果所有派生的 classes 都必须包含成员 a
和 b
, 那么在我看来,它们应该是基础 [=] 的一部分34=]。这样,您可以保证所有派生的 classes 都将包含成员 a
和 b
,并且您(或其他人)不会 运行 忘记的风险包括他们。此外,通过将成员包含在基 class 中,您不必在每个派生 class 中都包含它们,从而节省了内存。 C++ 的 virtual
为您提供了实现多态性的所有必要工具,当您创建一个 Base *
.
我还建议您对派生 class 中覆盖的虚函数使用关键字 override
,对派生 class 使用关键字 final
es 不打算成为基础 classes。您可以从 Scott Meyers 现代 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++ 规则禁止您在所有派生的 classes 中包含成员。
此外,如果您的所有成员都是 public
,那么您可以使用 struct
来避免在 classes 和继承中键入 public
方法。
struct Base
{
// all members are public
};
struct Derived : Base // public inheritance by default.
{
// all members are public
};
这有点基于意见,但这是我根据您发布的代码得出的想法。
由于您已将 Base
(所有 classes 均从中派生)抽象为 class,看来您想将其用作接口。
那样的话,还是分清接口继承和实现继承比较好。让 Base
没有任何数据,这意味着它不需要任何构造函数。
这是 Bjarne Stroustrup 给出的编码指南之一,标题为:When designing a class hierarchy, distinguish between implementation inheritance and interface inheritance
。
给出的原因是:
Implementation details in an interface make the interface brittle; that is, make its users vulnerable to having to recompile after changes in the implementation. Data in a base class increases the complexity of implementing the base and can lead to replication of code.
请注意,如果派生的 classes 中的数据是 public
。