为什么这个程序会尝试两次查找析构函数?

6
我正在尝试以下代码片段:

GeneralTemplate.h

(这是一个标题)

#ifndef _GENERATEMPLATE_H_
#define _GENERATEMPLATE_H_

#include <iostream>

template <class T>
class GeneralTemplate
{
  public:
  GeneralTemplate();
  GeneralTemplate(const GeneralTemplate &g);
  
  ~GeneralTemplate();
  
  GeneralTemplate& operator= (GeneralTemplate const& g);
  
  template <class M>
  void arbitraryFunction(const M &m);
};

#endif

main.cpp

#include "GeneralTemplate.h"

#include <iostream>

int main()
{
    GeneralTemplate<int> gInt;
    gInt.arbitraryFunction(2.3);
    return 0;
}

请注意,我没有为类模板的成员函数实现任何内容。但这不是问题。我知道该怎么做!如果我尝试编译main.cpp,我应该会得到链接错误,这就是我得到的。问题是为什么它会尝试两次查找析构函数(下面错误的最后两行)。
$g++ main.cpp 
/tmp/cckrdPCs.o: In function `main':
main.cpp:(.text+0x13): undefined reference to `GeneralTemplate<int>::GeneralTemplate()'
main.cpp:(.text+0x34): undefined reference to `void GeneralTemplate<int>::arbitraryFunction<double>(double const&)'
main.cpp:(.text+0x45): undefined reference to `GeneralTemplate<int>::~GeneralTemplate()'
main.cpp:(.text+0x61): undefined reference to `GeneralTemplate<int>::~GeneralTemplate()'
collect2: ld returned 1 exit status

我只收到一个未识别的析构函数引用(无论是clang++还是g++4.9.1,都在OS X 10.9上)。 - vsoftco
糟糕!应该使用_GENERALTEMPLATE_H_。但更改它并没有改变错误。 - toutnom
@toutnom 你使用的编译器/平台是什么? - vsoftco
<codereview>在我的看法中,你的头文件中似乎不需要包含#include <iostream>。</codereview> - Lightness Races in Orbit
3
@toutnom,我认为@Snefel和@AndreyT说得对!(PS:可以用throw()(或者在C++11中使用noexcept)标记该函数,仍然可能具有相同的行为,即不超过1个dtor调用。) - vsoftco
显示剩余4条评论
1个回答

8

这很可能与异常安全有关。如果arbitraryFunction抛出异常,堆栈需要被解除,这意味着gInt需要提前销毁。由于这一切都发生在main中,在那里不会再发生进一步的解除操作,所以它是否真的需要两次调用析构函数还是值得怀疑的...但你观察到的行为并不完全是荒谬的。


听起来对我来说很合理。 - Lightness Races in Orbit
@Snefdel,@vsoftco:只是确认你们所说的!使用“template <class M> void arbitraryFunction(const M &m) throw();”只会导致一个析构函数错误,而不是两个。因此,问题肯定与抛出异常有关。谢谢! - toutnom
2
@toutnom,你应该接受Sneftel的答案,因为它提供了正确的答案并解决了问题。在等待好的答案一段时间后,这是SO上的一个好习惯。 - vsoftco

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接