在模板化类中初始化静态指针

时间:2010-08-04 18:15:21

标签: c++ templates static-members

考虑这样一个类:

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.

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

上面的代码都是在标题中指定的,我提到的问题是链接步骤中的错误,因此找不到特定的符号。

5 个答案:

答案 0 :(得分:2)

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

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

同样,必须在您的问题中指定此类详细信息。如果没有它们,它就变成了随机的猜测。

答案 1 :(得分:1)

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

  

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

答案 2 :(得分:0)

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

  1. 明确初始化特定实例,例如

    int * MyClass<int>::staticPointerObject = NULL;
  2. 特别是当我有很多不同的类型时,这并不方便。

    1. 将指针包裹在类中,例如
    2. 
          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.
      

      这有点麻烦,但至少可用。为什么我可以实现变量对象而不是指向变量对象的指针?如果有什么我认为我会有更多的问题反过来(编译器提前知道指针是什么样的,但不是我的对象看起来像什么)。

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

答案 3 :(得分:0)

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

  

15 a的明确专业化   模板的静态数据成员是   声明中包含的定义   初始化器;否则,它是一个   宣言。 [注意:没有语法   用于定义静态数据   需要的模板的成员   默认初始化。模板&LT;&GT; 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;
}

答案 4 :(得分: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;
    }
};