如何用相同的参数从模板类继承到模板类

C++ How do I inherit from a template class, to a template class, with the same arguments

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

这个问题在这里已经有了答案除了,因为我读了上面的问题,仍然不知道哪里出了问题。编辑:不,它没有,这个错误的原因是不同的。

我正在尝试做这个:

template<typename T>
class base
{
protected:
    base() {}
    virtual ~base() {}
    virtual void method(void* const voidp) const = 0;
};
template<typename T>
class child : public base<T> // ERROR: child is not a template type
{
public:
    child(std::vector<T> arg)
        : _arg{arg}
    {
    }
    virtual ~child() {}
    void method(void* const voidp) const
    {
        for(template std::vector<T>::const_iterator it = _arg.begin(); it != _arg.end(); ++ it)
        {
            method2(voidp, *it);
        }
    }
protected:
    std::vector<T> _arg;
};

我有点困惑,因为这似乎是相同的链接的例子,除非我错了?

编辑:这是method2

void method2(void* const voidp, const double& arg) // second argument comes in both double and float formats
{
}
// so there is also a: void method2(void* const voidp, const float& arg)

不知道为什么你会看到

"//错误:child不是模板类型"

然而,一个明显的东西你错过了typenamestd::vector<T>::iterator it

应该是const_iterator

for(typename std::vector<T>::const_iterator it = _arg.begin(); 
     it != _arg.end(); 
      ++it)
{
    //method(voidp, *it); //<--- Assuming you've this somewhere not shown in current post
}

如果你和我有同样的问题,可能是你在代码的其他地方做了一个friend class定义?在使用不同的编译器和编译器选项在不同的系统上摆弄我的代码后,我侥幸使其编译成功。我相信这是因为在某个时候我从项目的文件中删除了一行,当检查这个文件时,我认为它曾经在那里有一个友类定义。我假设这导致编译器认为我没有写模板类?虽然我不完全相信这就是原因。

这个错误可能没有原因,除非可能有一个没有类模板的预先声明的类child

一个原因可能是你应该使用()而不是{}来初始化成员:

child(std::vector<T> arg)
        : _arg{arg}
    {
    }

应更正为:

child(std::vector<T> arg)
        : _arg(arg)
    {
    }

最好通过const引用传递:

child(const std::vector<T>& arg)
        : _arg(arg)
    {
    }

然而,还有其他一些东西可以改进以帮助程序:


for循环不能编译:

for(std::vector<T>::iterator it = _arg.begin(); it != _arg.end(); ++ it)
    {
        method2(voidp, *it);
    }

T是一个依赖名称,这意味着std::vector<T>::iterator应该被更正为typename std::vector<T>::iterator。你可以在这里阅读更多。

但是,std::vector<T>::iterator也应该更正为std::vector<T>::const_iterator。因为函数methodconst,所以const意味着函数将承诺不修改类的任何成员。然而,vector中的iterator begin()函数不是const限定的,这意味着编译器不知道是否要修改成员。因此,必须使用重载const_iterator begin() const,以便编译器显式地知道您不会修改任何成员。

另一个注意事项:如果你使用的是c++11,你可以使用range-for循环来使循环更短:
for(const auto& x : _arg)
{
    method2(voidp, x);
}

不需要在类中声明两次public:;一旦声明了一次public,接下来的所有内容都将是公开的,直到编译器到达另一个protected/private关键字,其他关键字反之亦然。

注意class的默认访问级别是private, struct的默认访问级别是public。因此,您的类可以稍微修改如下:

template<typename T>
class child : public base<T>
{
public:
    child(const std::vector<T>& arg)
        : _arg(arg)
    {
    }
    virtual ~child() {}
    void method(const void* voidp) const
    {
        for(typename std::vector<T>::const_iterator it = _arg.begin(); it != _arg.end(); ++ it)
        {
            method2(voidp, *it);
        }
    }
protected:
    std::vector<T> _arg;
};

同样适用于base类:

template<typename T>
class base
{
protected:
    base() {}
    virtual ~base() {}
    virtual void method(const void* voidp) const = 0;
};

与在函数声明中放置const关键字的位置保持一致:

你有:void* const voidpconst double& arg。如图所示,const关键字的位置不一致——一个在类型

的后面,一个在类型的前面

为了一致性,最好使用:const void* voidp, const double& argvoid* const voidp, double const& arg


最后,我使用MSVC编译了下面的代码,它工作得很好:
template<typename T>
    class base
    {
    protected:
        base() {}
        virtual ~base() {}
        virtual void method(const void* voidp) const = 0;
    };
template<typename T>
    class child : public base<T>
    {
    public:
        child(const std::vector<T>& arg)
            : _arg(arg)
        {
        }
        virtual ~child() {}
        void method(const void* voidp) const
        {
            for(typename std::vector<T>::const_iterator it = _arg.begin(); it != _arg.end(); ++it)
            {
                method2(voidp, *it);
            }
        }
    protected:
        std::vector<T> _arg;
    };

希望这对你有帮助