Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ &引用;“未定义引用”;到从静态方法访问的模板类的静态成员_C++_Templates_Static - Fatal编程技术网

C++ &引用;“未定义引用”;到从静态方法访问的模板类的静态成员

C++ &引用;“未定义引用”;到从静态方法访问的模板类的静态成员,c++,templates,static,C++,Templates,Static,我有一个静态类方法,需要访问指针MyTypePointer,因此必须声明为静态。由于它是一个模板类,我必须将方法放在头文件中,但我不能在头文件中定义MyTypePointer 由于MyTypePointer未声明,因此我得到了“未定义引用”错误。我怎样才能使它工作/声明MyTypePointer myclass.h template <typename A, typename B> class PathfindingClass { typedef std::vector&l

我有一个静态类方法,需要访问指针MyTypePointer,因此必须声明为静态。由于它是一个模板类,我必须将方法放在头文件中,但我不能在头文件中定义MyTypePointer

由于MyTypePointer未声明,因此我得到了“未定义引用”错误。我怎样才能使它工作/声明MyTypePointer

myclass.h

template <typename A, typename B>
class PathfindingClass {
    typedef std::vector<GenericEdgeClass<A, B>*> MyType;
    static MyType *MyTypePointer;
};

template <typename A, B>
void MyClass<A, B>::MyMethod(int x, int y) { 
    //do something with MyTypePointer
}
myclass.h
模板
类路径查找类{
typedef std::vector MyType;
静态MyType*MyTypePointer;
};
模板
void MyClass::MyMethod(intx,inty){
//用MyTypePointer做些什么
}

非常感谢。

在模板定义中,
静态MyType*MyTypePointer声明一个对象。您仍然必须在模板类定义之外定义它:

template <class A, class B>
typename PathfindingClass<A, B>::MyType*
PathfindingClass<A, B>::MyTypePointer;
模板
typename PathfindingClass::MyType*
PathfindingClass::MyTypePointer;

您仍然可以定义模板成员并显式地实例化它以实现所有需要的专门化。如果您坚持使用类模板的
状态
数据成员,这大概就是所需的

考虑到全局变量共享各种问题,包括初始化期间的依赖性问题,您最好使用
静态
成员函数包装数据成员:

template <typenane T>
class foo {
    // ...
    static X*& member() {
        static X* rc = ...;
        return rc;
    }
};
模板
福班{
// ...
静态X*&成员(){
静态X*rc=。。。;
返回rc;
}
};
在第一次调用函数时初始化局部变量,并且可以安全地使用对它的引用。这种方法也适用于模板


注意,我仍然建议避免使用全局变量!它们会在长期和短期内造成许多问题。使用它们的好处是一笔通常无法偿还的巨额债务。

这是一个迟来的答案,仅供参考,因为这个问题与另一个问题相关

声明但未定义的静态字段的最小中断示例可能是:

template<typename T>
class A
{
public:
    static T val;
    static void init()
    {
        val=0;
    }
};

int main()
{
    // A::init();
    A<double>::init();
    return 0;
}
模板
甲级
{
公众:
静态T值;
静态void init()
{
val=0;
}
};
int main()
{
//A::init();
A::init();
返回0;
}
修复方法只是在类定义之后定义静态字段:

template<typename T>
class A
{
public:
    static T val;
    static void init()
    {
        val=0;
    }
};

template<typename T> T A<T>::val; // only change here

int main()
{
    // A::init();
    A<double>::init();
    return 0;
}
模板
甲级
{
公众:
静态T值;
静态void init()
{
val=0;
}
};
模板TA::val;//这里只有零钱
int main()
{
//A::init();
A::init();
返回0;
}

您需要在模板声明(在标题中)中为它添加一个定义。实际上,您的问题是“定义”静态成员,而不是声明它。我认为您必须在CPP文件中显式地为类模板的每个实例化执行此操作。不过我可能错了@yzt否,应在标题中定义。链接器将关心多个实例化。@πάνταῥεῖ: 哦,谢谢!该死的,我一直在猜测链接器,并为自己制造这个特别的问题!如果多个源文件包含此头文件并使用相同的
A
B
实例化此模板,这是否会导致多个
MyTypePointer
实例!非常感谢。我将花一个晚上的时间来弄清楚那里到底发生了什么。@yzt-不。就像模板函数一样,实现负责排序重复项,最后只得到一个副本。@PeteBecker:噢,谢谢!该死的,我一直在猜测链接器,并为自己制造这个特别的问题!有趣!我很确定这在C++03中不起作用,但我可以在14[temp]第6段中看到,显然
静态
成员需要在所有翻译单元中定义,从而导致隐式实例化…谢谢。正是因为这个原因,我避免使用全局变量。另外,我想,在涉及模板时使用全局变量一开始可能不是那么容易?我意识到这可能不是正确的地方,但你能推荐一本书(DE,EN,FR,IT)来解释CPP更复杂的方面吗?@ USER 304941: Scott Meyers的经典著作是C++的C++。除此之外,有几本书涉及各个方面,但我不知道有哪一本书。关于模板,“”似乎是最完整的书,但它没有涵盖C++11引入的更改(即,在更新之前,它应该被视为“不完整的指南”)。