C 中的继承:在亲子类中定义变量

Inheritance in C++: define variables in parent-child classes

本文关键字:子类 定义 变量 继承      更新时间:2023-10-16

问题

我正在寻找定义亲子类中变量的最佳方法,以便通过指向其父班的指针来调用。
这是原始的:

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更好吗?谢谢

这种做法正确吗?

我认为这将变成一个基于意见的提问者。如果您的所有派生类都必须包括成员ab,则在我看来,它们应该是基类的一部分。这样,您可以确保所有派生的类都包括成员ab,并且您(或其他人(将不会承担忘记包括它们的风险。此外,通过将成员包括在基类中,您可以通过不必在每个派生的类中包含它们来保存内存。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
};

这在某种程度上是基于意见的,但这是我根据您发布的代码的想法。

由于您已将Base(从中衍生出所有类(为抽象类,因此您似乎要将其用作接口。

在这种情况下,最好区分接口继承和实现继承。令Base没有任何数据,这意味着它不需要任何构造函数。

这是Bjarne Stroustrup给出的编码指南之一: When designing a class hierarchy, distinguish between implementation inheritance and interface inheritance

给出的原因是:

接口中的实现详细信息使接口变脆;也就是说,使其用户容易在更改实施后必须重新编译。基类中的数据增加了实施基础的复杂性,并可能导致代码的复制。

请注意,如果派生类中的数据为public