有4个类:A,B,C和D. A类“有A”B,C类“有A”D。碰巧,C“是A”A,D“是A “B.在C ++中建模这些关系的最佳方法是什么?
A所拥有的B与C具有的相同。
示例:建筑物有入口,房屋有门。房子是建筑物,门是入口。
答案 0 :(得分:3)
class B {
};
class A {
B b; // A "has a" B
};
class C : public A { // C "is a" A
D d; // C "has a" D
};
class D : public B { // D "is a" B
};
答案 1 :(得分:1)
我认为你的设计存在缺陷。如果我理解正确,您希望限制基类成员变量的类型:
struct Entrance {};
struct Door : public Entrance {};
struct Building
{
Entrance * entrance; // raw pointer just for the sake of clarity
};
struct House : public Building
{
// Building::entrance must always be a door
};
你可以使用访问者(getter / setter)来实现entrance
并检查类型,如果入口不是门,则抛出异常,但这会破坏Liskov substitution principle:你不会能够操纵House
s,好像它们是Building
s:
struct Drawbridge : public Entrance {};
House house;
Drawbridge bridge;
Building & building = house;
building.setEntrance(bridge);
// Oups, I'm trying to install a drawbridge on my house!
有些库执行这种限制(例如,ReadOnlyCollection<T>
在尝试修改其内容时会抛出异常),但在我看来,这不是一个简洁的设计。如果集合的界面声明我可以add元素到集合,那么只读集合不集合(因为它不支持添加元素)。
此处可以应用相同的推理:House
不一个Building
,因为它不能包含所有类型的Entrance
。
答案 2 :(得分:1)
建筑物有入口,房子有门。房子是建筑物,门是入口。
struct Entrance {};
struct Door : Entrance {};
struct Building {
virtual Entrance& getEntrance() = 0;
};
struct House : Building {
virtual Entrance& getEntrance() {
return entrance;
}
private:
Door entrance;
};
typedef Building A;
typedef Entrance B;
typedef House C;
typedef Door D;
这是使用多态性的最接近的近似值。请特别注意,Building
无法实例化,因为它是“抽象的”。
否则,你不能A
有一个B
和 C
有一个D
,和让B
和D
都是同一个对象。
如果您想尝试让基座持有参考,请避免使用它:
struct Entrance {};
struct Door : Entrance {};
struct Building {
Building(Entrance& e) : e(e) {}
Entrance& e;
};
struct House : Building {
House() : Building(e) {}
Door e;
};
typedef Building A;
typedef Entrance B;
typedef House C;
typedef Door D;
由于House
的{{1}}构造函数在其创建Building
之前被调用,这充其量是可疑的(并且在最坏的情况下未定义...我'我必须查阅它。)
答案 3 :(得分:0)