在c ++中是否可以禁止在编译时调用某个函数?

时间:2011-09-23 05:27:51

标签: c++

我有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都是抽象类,但它们都有许多子类。

但有没有办法在编译时遇到错误?

4 个答案:

答案 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;
}