2

考虑这样一个类:

template < class T >
class MyClass
{
  private:
    static T staticObject;
    static T * staticPointerObject;
};
...
template < class T >
T MyClass<T>::staticObject; // <-- works
...
template < class T >
T * MyClass<T>::staticPointerObject = NULL; // <-- cannot find symbol staticPointerObject.

我无法弄清楚为什么我无法成功创建该指针对象。

上面的代码都是在头部指定的,我提到的问题是链接步骤出错,所以没有找到具体的符号。

4

5 回答 5

2

“找不到符号 staticPointerObject” - 这看起来像一个链接器错误消息。是吗?(必须在您的问题中指定这样的细节)。

如果是,它们很可能会发生,因为您将静态成员的定义放入了实现文件(.cpp 文件)中。为了使其正常工作,应将定义放入头文件(.h 文件)中。

同样,必须在您的问题中指定此类细节。没有它们,它就变成了随机的猜测盛宴。

于 2010-08-04T18:19:22.677 回答
1

我怀疑您的第一个示例的原因如下(来自 2003 C++ std 文档)。特别注意最后一句话——从你的例子来看,似乎没有什么“需要成员定义存在”。

14.7.1 隐式实例化 [temp.inst] 1 除非类模板特化已被显式实例化 (14.7.2) 或显式特化 (14.7.3),否则当在上下文中引用该类模板特化时会隐式实例化该类模板特化:需要完全定义的对象类型或当类类型的完整性影响程序的语义时。类模板特化的隐式实例化导致类成员函数、成员类、静态数据成员和成员模板的声明而不是定义或默认参数的隐式实例化;它会导致成员匿名联合的定义的隐式实例化。除非类模板或成员模板的成员已被显式实例化或显式特化,否则当在需要成员定义存在的上下文中引用特化时,成员的特化将被隐式实例化;特别是,静态数据成员的初始化(以及任何相关的副作用)不会发生,除非该静态数据成员本身的使用方式要求该静态数据成员的定义存在。

于 2011-12-31T03:18:33.733 回答
0

我找到了两种解决方案。它们都不是我所希望的 100%。

  1. 显式初始化特定实例,例如

    int * MyClass<int>::staticPointerObject = NULL;

这并不方便,尤其是当我有很多不同的类型时。

  1. 将指针包装在类中,例如

    template < class T >   
    class MyClass   
    {   
      private:   
        struct PointerWrapper   
        {   
          T * pointer;   
          PointerWrapper( void )   
            : pointer( NULL )   
          { }   
        };   
        T staticObject;   
        PointerWrapper staticPointerObject;   
    };   
    ...   
    template < class T >   
    T MyClass<T>::staticObject; // <-- works fine.   
    ...   
    template < class T >   
    MyClass<T>::PointerWrapper MyClass<T>::staticPointerObject; // <-- works fine.

这有点麻烦,但至少可以使用。为什么我可以实例化一个变量对象但不能实例化一个指向变量对象的指针?如果有的话,我会认为我会遇到更多问题(编译器提前知道指针的样子,但不知道我的对象的样子)。

如果有人有更好的答案,我很乐意看到它!

于 2010-08-04T18:38:30.730 回答
0

您对静态成员的第一个“定义”只是一个声明 - 这是标准的引用。

15 如果声明包含初始化器,则模板的静态数据成员的显式特化是定义;否则,它是一个声明。[注意:对于需要默认初始化的模板的静态数据成员的定义,没有语法。模板<> X Q::x; 无论 X 是否可以默认初始化(8.5),这都是一个声明。]

第二个定义应该有效。你确定你在一个编译单元中拥有所有可用的东西吗?错误消息的确切文本是什么?

以下使用 g++ 编译/运行 - 全部在一个文件中

#include <iostream>

template < class T >
class MyClass
{
  public:
    static T staticObject;
    static T * staticPointerObject;
};

template < class T >
T MyClass<T>::staticObject;

template < class T >
T * MyClass<T>::staticPointerObject = 0; 

int main(int argc, char **argv)
{
  int an_int = 5;
  MyClass<int>::staticPointerObject = &an_int;
  std::cout << *MyClass<int>::staticPointerObject << std::endl;

  char a_char = 'a';
  MyClass<char>::staticPointerObject = &a_char;
  std::cout << *MyClass<char>::staticPointerObject << std::endl;
}
于 2010-08-04T18:59:33.560 回答
0

我一直使用以下技巧。这个想法是将您的静态放在一个函数中,并且只能从该函数访问它。这种方法还允许您避免在文件中声明静态.cpp文件的需要——所有内容都可以存在于.h文件中。按照您的示例代码:

template < class T >
class MyClass
{
  public:
    static T * getObject() {
      // Initialization goes here.
      static T * object = NULL; // or whatever you want
      return pointerObject;
    }
};
于 2011-02-19T23:38:57.500 回答