我有2个班级:
class Entity {
void addChild(Entity* e);
};
class Control : public Entity {
};
我想要做的是不允许将Control添加为非Control的子项。所以,例如:
Control c;
Entity e;
e.addChild(c); // This line would throw an error (at compile time if possible);
我想到的第一件事是将其添加到实体:
void addChild(Control* c){
assert(false);
};
注意:Entity和Control都是抽象类,但它们都有许多子类。
但有没有办法在编译时遇到错误?
答案 0 :(得分:5)
您可以声明该功能,但不要实现它。如果您尝试使用它,则会出现链接器错误。
答案 1 :(得分:2)
void addChild(Control c){ 断言(假); };
但有没有办法在编译时遇到错误?
如果您的实现具有某些C ++ 11支持,或者static_assert
可以在任何实现中使用,则可以使用BOOST_STATIC_ASSERT
。但是,我建议你适当地重新设计你的层次结构。另请注意,您在建议addChild
的定义中混合了指针和对象。
答案 2 :(得分:2)
在C ++ 0x中,您寻求的机制确实可行。
class Entity {
public:
void addEntity(Entity*);
void addEntity(Control*) = delete;
};
但它无法正常运作!
int main() {
Entity e;
Control c;
e.addEntity(&c); // ERROR
Entity& ec = c;
e.addEntity(&ec); // OK
}
正如其他人所说,你的用例很可疑。如果您不希望Control
类作为Entity
传递,则删除继承关系。如果保留继承关系,那么只要期望Entity
,就可以传递Control
。
答案 3 :(得分:2)
通过一些模板专业化,可以在某种程度上完成。但是,我能够完成这项工作的唯一方法是在子元素本身上使用“addChild”方法(重命名为“AttachToParent”)。并通过引用而不是指针传递。模板专业化很难!
class Entity
{
public:
void AddChild(Entity* pChild);
};
class Control : public Entity
{
public:
template <typename T>
void AttachToParent(T& parent)
{
parent.You_are_trying_to_attach_Control_to_something_not_a_Control();
}
template <>
void AttachToParent<Control>(Control& parent)
{
parent.AddChild(this);
}
};
int main(int argc, char** argv)
{
Entity eParent;
Entity eChild;
Control cChild1;
Control cChild2;
eParent.AddChild(&eChild); // legal
cChild2.AttachToParent(cChild1); // allowed
//cChild1.AttachToParent(eParent); // uncomment this line and a compile error will occur
return 0;
}