这个问题已经有一个答案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)
答案 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
。由于函数method
为const
,const
表示函数将承诺不修改类的任何成员。但是,向量中的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
,public
的默认访问级别为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& arg
或void* 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;
};
希望这会有所帮助:)