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

发布于 2024-09-13 05:59:45 字数 458 浏览 5 评论 0原文

考虑这样一个类:

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.

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

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

Consider a class like so:

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.

I am having trouble figuring out why I cannot successfully create that pointer object.

The above code is all specified in the header, and the issue I mentioned is an error in the link step, so it is not finding the specific symbol.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

百变从容 2024-09-20 05:59:45

“无法找到符号 staticPointerObject” - 这看起来像链接器错误消息。是吗? (必须在您的问题中指定此类详细信息)。

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

同样,必须在您的问题中指定此类详细信息。没有他们,它就会变成一场随机的猜测盛宴。

"Cannot find symbol staticPointerObject" - this looks like a linker error message. Is it? (Details like this have to be specified in your question).

If it is, them most likely it happens because you put the definition(s) of your static member(s) into an implementation file (a .cpp file). In order for this to work correctly, the definitions should be placed into the header file (.h file).

Again, details like this have to be specified in your question. Without them it turns into a random guess-fest.

红玫瑰 2024-09-20 05:59:45

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

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

I suspect the reason your first example is the following (from the 2003 C++ std document). Note particularly the last sentence -- from your example, there seems to be nothing "that requires the member definition to exist".

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.

撩起发的微风 2024-09-20 05:59:45

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

15 的显式专业化
模板的静态数据成员是
定义(如果声明包含)
初始化器;否则,它是一个
宣言。 [注意:没有语法
静态数据的定义
需要的模板成员
默认初始化。模板>> X
问::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;
}

Your first "definition" of static member is but a declaration - here is a quote from the standard.

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). ]

The second definition should work. Are you sure you have everything available in one compilation unit? What is teh exact text of error message?

The following compiles/runs with g++ - all in one file

#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;
}
梨涡少年 2024-09-20 05:59:45

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

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

    int * MyClass::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.

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

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

I have found two solutions. Neither of them are 100% what I was hoping for.

  1. Explicitely initialize the specific instance, e.g.

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

This is not convinient especially when I have a lot of different types.

  1. Wrap the pointer inside the class, e.g.

    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.

This is a bit of a hassle, but at least usable. Why is it I can instansiate a variable object but not a pointer to a variable object? If anything I would think I'd have more problems the other way around (the compiler knows ahead of time what a pointer looks like, but not what my object looks like).

If someone has a better answer I'd love to see it!

鯉魚旗 2024-09-20 05:59:45

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

template < class T >
class MyClass
{
  public:
    static T * getObject() {
      // Initialization goes here.
      static T * object = NULL; // or whatever you want
      return pointerObject;
    }
};

I use the following trick all the time. The idea is to put your static in a function, and access it only from that function. This approach also allows you to avoid the need to declare your static in a .cpp file -- everything can live in the .h file. Following your example code:

template < class T >
class MyClass
{
  public:
    static T * getObject() {
      // Initialization goes here.
      static T * object = NULL; // or whatever you want
      return pointerObject;
    }
};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文