12

根据我最喜欢的作家Scott Meyers 先生的说法,私有继承和组合意味着同样的事情,也就是 Has-A 关系。因此,可以从组合中获得的所有内容(包含,当类 A 具有类 B 作为其成员时)都可以通过私有继承获得,反之亦然。

所以下面的代码应该是一个Has-A关系,但在我看来,它不是!

class A : private boost::noncopyable {.. this is irrelevant };

谁能告诉我我失踪了?或者如何通过组合来实现这段代码?

4

4 回答 4

16

你的例子可以通过这样的组合来实现:

class A {
private:
    class B {
        B(const B&) = delete;
        B& operator=(const B&) = delete;
    } b;
};

A是不可复制的,因为它的成员b是不可复制的。

于 2018-06-04T12:18:27.450 回答
6

您的示例仍然是 HAS-A 关系。

以下面的类为例,它大致相当于boost:noncopyable

class X {
private:
    X(const X &);
    X &operator=(const X &);
public:
    X() {}
};

以下两个类具有相同的功能:

class A : private X {
public:
    int a;
    char b;
};

class B {
public:
    int a;
    char b;
    X x;
};

在这个例子中,A继承自XwhileB包含一个X. A无法复制,因为它无法调用父级的复制构造函数,B也无法复制,因为它无法调用其成员之一的复制构造函数。

A a1;
A a2(a1);   // error
B b1;
B b2(b1);   // error
于 2018-06-04T12:29:20.103 回答
4

boost::noncopyable没有真正的语义意义,这只是一个禁止孙子的实现细节。

class A : private boost::noncopyable {};

A没有, 因为是空的,无论是字面意思还是意义 在这里,您会说“不可复制”,但我一般同意迈耶斯在一般情况下的观点。boost::noncopyableboost::noncopyableA

于 2018-06-04T12:18:40.347 回答
1

可以通过避免讨论特定示例的细节来回答这个问题。一个公开继承的类从定义其父级语义的所有内容开始——它的公共函数,以及它的公共状态变量(如果有的话)。如果这些都没有被覆盖,则它符合Liskov 替换原则,并且这是一个被广泛接受的设计原则,即应该以保持可替换性的方式覆盖这些属性。

对于私有继承,这些都不适用,除非程序员选择在派生类中实现(或重新实现)父类的所有公共属性,以保持可替换性。由于 C++ 不需要私有派生类来实现其父类的公共方法和变量的版本,因此这与派生类包含父类的实例并没有什么不同(除了代码中的微小和公式化更改)私人会员。特别是,对于私有继承,派生类在任何功能或操作方面都不是父类型的子类型,并且如果您的语言将派生类视为子类型,

于 2018-06-04T17:35:09.653 回答