关于链表:模板类,静态函数编译错误c ++

Template class, static function compile error c++

我在链表类中定义了以下函数。头文件中的声明如下:

1
2
3
4
5
6
template <typename T>
class RingBuffer
{
  ...//stuff
  static BLink * NewLink (const T&); // allocator
};

blink是ringbuffer类中的"link"类。以下实施代码:

1
2
3
4
5
6
7
template <typename T>
RingBuffer<T>::BLink * RingBuffer<T>::NewLink( const T& t ) // this is line 114
{
  // create a new link in linked list
  ....
  ....
}

这是一个编译错误:

/ringbuff.cpp:114:错误:在*标记之前需要构造函数、析构函数或类型转换

我很难理解为什么它在返回值之前需要一个预期的构造函数、析构函数或类型转换。


这里的问题是,您所引用的是嵌套的依赖类型名(即,blink嵌套在依赖模板参数的ringbuffer中)。

在这种情况下,您需要通过声明RingBuffer::BLink是一个实际的类型名来帮助编译器。您可以使用typename关键字来完成此操作。

1
2
3
4
5
template <typename T>
typename RingBuffer<T>::BLink * RingBuffer<T>::NewLink(const T& t)
{
  // ...
}

说明:

在模板参数T已知之前,编译器无法知道RingBuffer::BLink是类型名还是静态成员。当编译器解析您的函数模板时,T未知,解决歧义的规则是默认为"这不是类型名"。

另一个简短的例子(公然复制Scott Meyers的有效C++):

1
2
3
4
5
6
template<typename C>
void print2nd(const C& container)
{
  C::const_iterator * x;
  …
}

这也许能更好地说明问题,因为它更紧凑。正如前面所说,对于解析器来说,不清楚C::const_迭代器是一个类型名还是一个静态数据成员,因为它不知道解析这部分代码时C是什么(稍后它可能会知道模板实际实例化的时间)。因此,为了减轻编译器实现者的生命,这种模糊性被解决为"不是类型名",如果程序员想要使用嵌套在依赖模板参数的任何内容中的类型名,他/她必须在名称前面使用typename关键字,以让编译器知道应该将其视为类型名。

不幸的是,当在基类列表或成员初始化列表中的基类标识符中使用嵌套的依赖类型名时,该规则有一个例外。

1
2
3
4
5
6
7
8
9
10
11
12
13
template<typename T>
struct Base {
  struct Nested {
    Nested(int) {}
  };
};

template<typename T>
struct Derived : public Base<T>::Nested { // typename not allowed here
  Derived(int i)
    : Base<T>::Nested(i) // nor here
  {}
};

顺便说一句:您应该将控制台客户端的字符集设置为utf-8,这样您就可以得到‘*’,而不是a*a


编译器消息有点误导人。基本上表示语法/解析错误。确保原型在编译文件中可见,确保环缓冲区声明为模板。正如其他人所说,课后检查半列。