派生类构造函数以基类为参数(这是好的做法吗?

Derived class constructor taking base class as argument (Is it Good practice?)

本文关键字:构造函数 基类 参数 派生      更新时间:2023-10-16

我下面有两个简单的类,一个是基础类,另一个是从它派生出来的。
在派生类中有两个构造函数,一个采用 base 和 derived 所需的所有参数,另一个采用 Base 类引用本身作为参数。

我知道将基类引用作为参数的构造函数不是一个好的做法。
但是,我想知道为什么它不被认为是一种好的做法?它实现了与其他构造函数相同的目标。

有人可以澄清为什么这不是一个好的 OOP 实践吗?

class Base
{
public:
    Base(int a, int b):
        m_a(a),
        m_b(b)
    {}
    Base(const Base& b):
        m_a(b.m_a),
        m_b(b.m_b)
    {}
    ~Base() {}
protected:
    int m_a;
    int m_b;
};
class Derived : public Base
{
public:
    // Constructor which takes base class argument and initializes base
    Derived(Base &base, int c):
        Base(base),
        m_c(c)
    {}

    Derived(int a, int b, int c):
        Base(a, b),
        m_c(c)
    {}
    ~Derived() {}
private:
    int m_c;
};
int main()
{
    Base base(1,2);
    Derived derived1(base, 3); //
    Derived derived2(1,2, 3);
}

有必要知道在其中指定第一个派生构造函数的上下文。

但是,也许使用 const Base 参数定义它会更优雅。像这样:

Derived(const Base &base, int c):
        Base(base),
        m_c(c)
    {}

因此,它告诉编译器保护base对象的状态。

此外,如果您使用的是 c ++ - 11,那么您可能有兴趣声明:

using Base::Base;

Derived 类中,是什么使该Derived继承了 Base 的构造函数。 因此,您可以在main()中添加:

Derived derived3(1,2);

这将完美地编译。

在 c++-11 中,您还可以为m_c数据成员设置默认值。

int m_c = 0;

因此,从Base继承的构造函数将使Derived处于一致状态

我相信

你展示的代码不是糟糕的 OOP 实践。Derived的用户知道并有权访问Base,因为Derived使用公共继承。因此,您不会添加任何依赖项,因此不会使任何内容更具限制性或复杂性。

也就是说,即使Derived使用受保护或私有继承,也不一定是不好的做法,这取决于Derived的用户是否知道类Base

想象一下:

class Derived { // no inheritance
public:
    void doSomething(const X& b); // `X` could be `Base`, `Foo`, or `std::string` for that matter...
};

你会说上述做法不好吗?我认为不是。这里的关键,就像你提供的代码一样(假设你按照lrleon的建议将const限定符添加到Base&),是你正在使用Base作为值类型。 Derived 没有持有指向要传入的基本对象的指针/引用,因此您拥有的是正常的参数传递,并且参数传递没有任何异常或不良做法。