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 都必须包含成员 ab 那么在我看来,它们应该是基础 [=] 的一部分34=]。这样,您可以保证所有派生的 classes 都将包含成员 ab,并且您(或其他人)不会 运行 忘记的风险包括他们。此外,通过将成员包含在基 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