让我们考虑以下三个文件。从专门的方法捕捉异常
tclass.h:
#include <iostream>
#include <vector>
template<typename rt>
class tclass
{
public:
void wrapper()
{
//Storage is empty
for(auto it:storage)
{
}
try
{
thrower();
}
catch(...)
{
std::cout << "Catch in wrapper\n";
}
}
private:
void thrower(){}
std::vector<int> storage;
};
spec.cpp:
#include "tclass.h"
//The exact type does not matter here, we just need to call the specialized method.
template<>
void tclass<long double>::thrower()
{
//Again, the exception may have any type.
throw (double)2;
}
main.cpp中:
#include "tclass.h"
#include <iostream>
int main()
{
tclass<long double> foo;
try
{
foo.wrapper();
}
catch(...)
{
std::cerr << "Catch in main\n";
return 4;
}
return 0;
}
我使用Linux的x64,GCC 4.7 。2,该文件被编译使用此命令:
g++ --std=c++11 *.cpp
第一次测试:如果我们运行上面的程序,它说:
terminate called after throwing an instance of 'double'
Aborted
二测:如果我们在tclass.h
文件发表评论for(auto it:storage)
,该程序将捕获main
函数中的例外。 WAT为什么?它试图迭代空向量导致堆栈损坏吗?
第三个测试:让我们取消注释for(auto it:storage)
行并将方法专业化从spec.cpp
移动到main.cpp
。然后,例外被捕获在wrapper
。这怎么可能,为什么可能的内存腐败不会影响这种情况?
我也试着用不同的优化级别和-g
进行编译,但结果是一样的。
然后我在Windows 7 x64,VS2012 Express上试了一下,用x64版本的cl.exe编译,没有额外的命令行参数。在第一次测试中,这个程序没有产生任何输出,所以我认为它只是默默地崩溃,所以结果与Linux版本类似。对于第二次测试,它再次没有输出,所以结果与Linux不同。对于第三次测试,结果与Linux结果类似。
此代码中是否有任何错误,因此它们可能会导致此类行为?可能第一次测试的结果是由编译器中可能存在的错误引起的?
如何和:
spec.cpp:6: multiple definition of 'tclass<long double>::thrower()'
您可以在您的.h声明专业化纠正代码你在哪里声明和定义模板专业化? –
@Juraj我专门研究'spec.cpp'中的'thrower'方法。我是否需要专门做其他事情才能使其正常工作? – Sergey
@Juraj明白!当然,没有必要专门研究整个类,但解决方案是在头上添加声明(即'template <> void tclass :: thrower();')。它适用于03和11.谢谢! –
Sergey