2010-08-04 104 views
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. 

我无法弄清楚为什么我不能成功地创建一个指针对象。

上面的代码全部在头文件中指定,我提到的问题是链接步骤中的错误,所以它没有找到特定的符号。

回答

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. 

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

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

2

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

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

再次,像这样的细节必须在你的问题中指定。没有它们就会变成随机猜测。

+0

我更新了我原来的帖子。这是一个链接器错误。 – Anthony 2010-08-04 18:43:01

0

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

15 An explicit specialization of a static data member of a template is a definition if the declaration includes an initializer; otherwise, it is a declaration. [Note: there is no syntax for the definition of a static data member of a template that requires default initialization. template<> X Q::x; This is a declaration regardless of whether X can be default initialized (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; 
} 
+0

我正在使用PowerPC 604的GNU交叉编译器。确切的输出是 未定义的符号:_t16DynamicSingleton1ZQ213SingletonTest12SharedObject $ ptr(binding 1 type 0) ld错误:模块包含未定义的符号并且可能无法使用。 最初我有一个* .cpp文件内的定义,但我已经将它移到了头文件中,所以它肯定应该是可见的。 我发现了一些Google提及的不得不采取我在下面的答案的第一部分中提到的步骤。我正在使用的编译器可能只是不支持我想要做的事情(也就是,你刚刚做了什么)。 – Anthony 2010-08-04 19:28:31

+0

我应该提到它在这一点上与VxWorks 5.5链接。 – Anthony 2010-08-04 19:29:09

+0

你可以在那个错误信息中去掉符号吗?我的C++ filt拒绝这样做。 – Arkadiy 2010-08-04 20:10:19

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; 
    } 
}; 
1

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

14.7.1 Implicit instantiation [temp.inst] 1 Unless a class template specialization has been explicitly instantiated (14.7.2) or explicitly specialized (14.7.3), the class template specialization is implicitly instantiated when the specialization is referenced in a context that requires a completely-defined object type or when the completeness of the class type affects the semantics of the program. The implicit instantiation of a class template specialization causes the implicit instantiation of the declarations, but not of the definitions or default arguments, of the class member functions, member classes, static data members and member templates; and it causes the implicit instantiation of the definitions of member anonymous unions. Unless a member of a class template or a member template has been explicitly instantiated or explicitly specialized, the specialization of the member is implicitly instantiated when the specialization is referenced in a context that requires the member definition to exist; in particular, the initialization (and any associated side-effects) of a static data member does not occur unless the static data member is itself used in a way that requires the definition of the static data member to exist.