如何为模板类参数指定所需的继承

How do I specify a required inheritance for a template class argument?

本文关键字:继承 参数      更新时间:2023-10-16

我有以下结构:

class ElementEx
{
public:
    ElementEx() {}
    AddChild(ElementEx* element) 
    {
        // some stuff
    }
};
class A : ElementEx
{
public:
    A() {}
};
class B : ElementEx
{
public:
    B() {}
};

template <class T>
class MyNewClass : public T
{
public:
    MyNewClass()
    {
        ElementEx* newElement = new ElementEx();
        AddChild(newElement);
    }
};

创建 MyNewClass 对象时,T 必须继承自 A 或 B,因此 MyNewClass 将从 ElementEx 继承。但是在我的示例中,编译器不知道这一点,也无法弄清楚AddChild是什么。如何确保 T 类是 ElementEx 的后代?

我在想象做

((ElementEx*)this)->AddChild(newElement);

但这似乎真的很不优雅(如果错误的类型被输入为 T,并且容易出错),我认为一定有更好的方法来做到这一点。

编译器在这里抱怨,因为它不知道AddChild在第一次传递期间依赖于T。 可以通过在调用前面加上 this-> 来使AddChild成为依赖名称,从而在已知T时延迟查找到第二次传递。

只要

你满足于父类支持AddChild接受ElementEx,你就可以使用正常的编译器错误轻松做到这一点。

在修复了代码中的一堆错误(A 和 B 私下继承,你所有的类都有私有构造函数,AddChild没有返回类型)我能够通过向 AddChild 调用中添加 this-> 来使其正常工作,因为AddChild是一个依赖名称,您可以通过限定类型或添加 this-> 来向编译器指示。如果您预计不需要对该方法进行虚拟调用,则可以调用ElementEx::AddChild来强制进行正确的查找。更正后的代码如下。

class ElementEx
{
public:
    ElementEx() {}
    void AddChild(ElementEx* element)
    {
        // some stuff
    }
};
class A : public ElementEx
{
public:
    A() {}
};
class B : public ElementEx
{
public:
    B() {}
};

template <class T>
class MyNewClass : public T
{
public:
    MyNewClass()
    {
        ElementEx* newElement = new ElementEx();
        this->AddChild(newElement);
    }
};
struct Bad {};
int main()
{
    MyNewClass<B> b;          // Compiles.
    MyNewClass<Bad> bad;      // error: 'class MyNewClass<Bad>' has no member named 'AddChild'
}

有几种方法可以很好地做到这一点,但它们都有使用 1.) 静态断言的基础。 2)静态评估函数。

个人,我会使用(在构造函数中)

static_assert(std::is_base_of<ElementEx,T>::value,"T must derive from ElementEx")

但可能有一个更好的方法。您问题的 X 部分是什么(您想通过这种奇怪的继承结构实现什么目标?