C++ 在c++;禁止在编译时调用某个函数?

C++ 在c++;禁止在编译时调用某个函数?,c++,C++,我有两门课: class Entity { void addChild(Entity* e); }; class Control : public Entity { }; 我想做的是不允许添加控件作为非控件的子控件。例如: Control c; Entity e; e.addChild(c); // This line would throw an error (at compile time if possible); 我想到的第一件事是将此添加到实体: void addChil

我有两门课:

class Entity {
   void addChild(Entity* e);
};

class Control : public Entity {

};
我想做的是不允许添加控件作为非控件的子控件。例如:

Control c;
Entity e;
e.addChild(c); // This line would throw an error (at compile time if possible);
我想到的第一件事是将此添加到实体:

void addChild(Control* c){
    assert(false);
};
注意:实体和控件都是抽象类,但都有许多子类


但是有没有办法在编译时得到一个错误?

您可以声明这个函数,但不要实现它。如果您尝试使用链接器,则会出现链接器错误。

您可以声明该函数,但不要实现它。如果您尝试使用链接器,则会出现链接器错误

void addChild(控制c){ 断言(假); };

但是有没有办法在编译时得到一个错误呢

如果您的实现有一些C++11支持,您可以使用
static\u assert
,或者
BOOST\u static\u assert
在任何实现中都可以使用。但是,我建议您适当地重新设计层次结构。还请注意,您在建议的
addChild
定义中混合了指针和对象

void addChild(控制c){ 断言(假); };

但是有没有办法在编译时得到一个错误呢


如果您的实现有一些C++11支持,您可以使用
static\u assert
,或者
BOOST\u static\u assert
在任何实现中都可以使用。但是,我建议您适当地重新设计层次结构。还请注意,您在建议的
addChild
定义中混合了指针和对象。

在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
}

正如其他人所建议的,您的用例是可疑的。如果不希望将
控件
类作为
实体
传递,请删除继承关系。如果保持继承关系,则无论何时需要
实体
,都可以传递
控件

在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
}

正如其他人所建议的,您的用例是可疑的。如果不希望将
控件
类作为
实体
传递,请删除继承关系。如果您保持继承关系,那么无论何时需要
实体
,都可以传递
控件

通过一点模板专门化,就可以在某种程度上完成。但是我能做到这一点的唯一方法是在子元素本身上使用“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;
}
类实体
{
公众:
void AddChild(实体*pChild);
};
类控制:公共实体
{
公众:
样板
无效附加所有权(T和母公司)
{
家长。您正在尝试将控制附加到非控制()的对象上;
}
样板
无效附加所有权(控制权和母公司)
{
parent.AddChild(this);
}
};
int main(int argc,字符**argv)
{
实体分租;
实体梯次;
对照组1;
对照组2;
eParent.AddChild(&eChild);//合法
cChild2.附件(cChild1);//允许
//cChild1.AttachToParent(eParent);//取消对此行的注释,将发生编译错误
返回0;
}

通过一点模板专门化,可以在某种程度上完成。但是我能做到这一点的唯一方法是在子元素本身上使用“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;
}
类实体
{
公众:
void AddChild(实体*pChild);
};
类控制:公共实体
{
公众:
样板
无效附加所有权(T和母公司)
{
家长。您正在尝试将控制附加到非控制()的对象上;
}
样板
无效附加所有权(控制权和母公司)
{
parent.AddChild(this);
}
};
int main(int argc,字符**argv)
{
实体分租;
实体梯次;
对照组1;
对照组2;
eParent.AddChild(&eChild);//合法
cChild2.附件(cChild1);//允许
//cChild1.AttachToParent(eParent);//取消对此行的注释,将发生编译错误
返回0;
}

我建议重新设计类层次结构,这样就不需要在派生类中使用固有的函数。也许可以将
实体
作为抽象类,那么就不可能实例化实体对象了。我支持sashang:如果你需要明确禁止使用派生类作为基类,那么很有可能公共继承不是你想要做的。公共继承的要点是可以使用派生类作为基类。如果必须禁止,这可能是类布局和设计结构中的一个问题。我建议重新设计类层次结构,这样就不会在派生类中使用任何不想使用的固有函数。也许可以将
实体
作为一个抽象类,那么就不可能实例化实体对象了。我支持sashang:如果你需要明确禁止使用派生类作为基类,那么很有可能公共继承不是你想要做的。公共继承的要点是可以使用派生类作为基类。如果必须禁止,这可能是类布局和设计结构中的一个问题。如果将控件添加为基类(实体)指针,这仍然没有帮助。没错,但这是一个需要重新设计的基本问题。如果将控件添加为基类(实体)指针,这仍然没有帮助。没错,但这是一个需要重新设计的基本问题。