考虑这样一个类:
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 :(得分: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%。
明确初始化特定实例,例如
int * MyClass<int>::staticPointerObject = NULL;
特别是当我有很多不同的类型时,这并不方便。
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;
}
};