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

时间:2015-08-23 19:17:27

标签: c++ oop templates c++11 inheritance

这个问题已经有一个答案here ,除了因为我读了这个问题并且仍然无法弄清楚出了什么问题。编辑:不,它不会导致此错误的原因不同。

我正在尝试这样做:

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)

3 个答案:

答案 0 :(得分:0)

不确定为什么你会看到

  

&#34; //错误:孩子不是模板类型&#34;

然而,typename

之前,std::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
}

答案 1 :(得分:0)

如果您遇到与我相同的问题,可能是您在代码中的其他地方做了friend class定义?在使用不同编译器和编译器选项在不同系统上使用我的代码之后,我开始编译它。我相信这是因为在某些时候我从项目的文件中删除了一行,并且在检查这个文件时,我认为它曾经在那里有一个朋友类定义。我认为这导致编译器认为我没有编写模板类?虽然我不完全相信这就是原因。

答案 2 :(得分:-1)

没有可能出现这种错误的原因,除非可能没有类模板预先声明了类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。您可以阅读有关此here的更多信息。

但是,std::vector<T>::iterator也应更正为std::vector<T>::const_iterator。由于函数methodconstconst表示函数将承诺不修改类的任何成员。但是,向量中的iterator begin()函数不是const限定的,这意味着编译器不知道您是否要修改成员。因此,必须使用重载const_iterator begin() const,以便编译器明确知道您不会修改任何成员。

另一个注意事项:如果你使用c++11,你可以通过使用range-for循环来缩短循环次数:

for(const auto& x : _arg)
{
    method2(voidp, x);
}

无需在课堂上两次声明public:;一旦public被声明一次,以下所有内容都将公开,直到编译器到达另一个protected / private关键字,反之亦然。

请注意,class的默认访问权限级别为privatepublic的默认访问级别为struct。因此,您的课程可以略微修改为:

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 voidp,然后是const 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;
    };

希望这会有所帮助:)