根据我最喜欢的作者Mr Scott Meyers,私有继承和组合意味着同样的事情,即Has-A关系。因此,可以通过私有继承获得从组合中获得的所有东西(包含A类,其中A类具有B类成员),反之亦然。
所以下面的代码应该是Has-A关系,但从我的观点来看,它不是!
class A : private boost::noncopyable {.. this is irrelevant };
任何人都可以告诉我,我失踪了吗?或者如何通过合成来实现此代码?
答案 0 :(得分:15)
您的示例可以通过以下组合实现:
class A {
private:
class B {
B(const B&) = delete;
B& operator=(const B&) = delete;
} b;
};
A
是不可复制的,因为其成员b
是不可复制的。
答案 1 :(得分: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
从X
私下继承,而B
包含X
的实例。 A
无法复制,因为它无法调用父级的复制构造函数,并且B
无法复制,因为它无法调用其中一个成员的复制构造函数
A a1;
A a2(a1); // error
B b1;
B b2(b1); // error
答案 2 :(得分:4)
boost::noncopyable
没有真正的语义含义,这只是一个禁止孙子的实现细节。
class A : private boost::noncopyable {};
A
没有拥有 boost::noncopyable
,因为boost::noncopyable
在字面上和意义上都是空的。在这里,你会说“A
是不可复制的”,但我通常同意迈耶斯在一般情况下的观点。
答案 3 :(得分:1)
This question can be answered in a way that avoids the specifics of discussing a particular example. A class that inherits publicly starts off with everything that defines its parent's semantics - its public functions, and also its public state variables, if it has any. If none of these are overridden, it conforms to the Liskov substitution principle, and it is a widely-accepted design principle that overrides of these properties should be done in such a way that preserves substitutability.
With private inheritance, none of this applies, unless the programmer chooses to implement (or re-implement), in the derived class, all the public properties of the parent class, in a way that preserves substitutability. As C++ does not require a privately-derived class to implement versions of its parent's public methods and variables, this is no different (other than minor and formulaic changes in the code) than if the derived class instead contained an instance of the parent class as a private member. In particular, with private inheritance, the derived class is not, in any functional or operational way, a sub-type of the parent's type, and if your language treats derived classes as if they are subtypes, an opportunity for misunderstanding and confusion has been created (though it should be noted that unless your language has a way to enforce the semantic validity of subtypes (which C++ does not), then this is effectively a matter of style.)