【发布时间】:2016-03-06 22:44:21
【问题描述】:
在决定提出这个问题之前,我搜索了整个互联网和堆栈溢出,所以如果我忽略了一些非常简单的问题,请见谅,但这里就是这样。
使用 Visual Studio 2010,我有一个这样的课程:
class MyClass {
public:
/* Constructors and other methods omitted */
template <typename T1>
CString operator()(const T1 &a1) { return _fmt("dummy", a1); }
template <typename T1, typename T2>
CString operator()(const T1 &a1, const T2 &a2) { return _fmt("dummy", a1, a2); }
template <typename T1, typename T2, typename T3>
CString operator()(const T1 &a1, const T2 &a2, const T3 &a3) { return _fmt("dummy", a1, a2, a3); }
template <typename T1, typename T2, typename T3, typename T4>
CString operator()(const T1 &a1, const T2 &a2, const T3 &a3, const T4 &a4) { return _fmt("dummy", a1, a2, a3, a4); }
private:
CString _fmt(const char *dummy, ...);
};
这个想法是为 MyClass 提供一个 operator () 重载,其作用类似于 sprintf() 格式化程序,除了格式字符串包含在 MyClass 实例本身中。我会使用可变参数模板,唉,Visual Studio 2010 不支持它们,因此半生不熟的解决方案是提供许多 operator () 的重载模板版本,它们反过来都调用使用 va_list/va_start()/va_end() 的私有 _fmt() 函数和因此需要强制使用无用的第一个参数(因此名称为 “dummy”)。
编译正常,但是链接会出现如下错误:
error LNK2019: unresolved external symbol "private: class ATL::CStringT<char,class ATL::StrTraitATL<char,class ATL::ChTraitsCRT<char> > > __cdecl MyClass::_fmt(char const *,...)" (?_fmt@MyClass@@AAA?AV?$CStringT@DV?$StrTraitATL@DV?$ChTraitsCRT@D@ATL@@@ATL@@@ATL@@PBDZZ) referenced in function "public: class ATL::CStringT<char,class ATL::StrTraitATL<char,class ATL::ChTraitsCRT<char> > > __thiscall MyClass::operator()<char [261]>(char const (&)[261])" (??$?R$$BY0BAF@D@MyClass@@QAE?AV?$CStringT@DV?$StrTraitATL@DV?$ChTraitsCRT@D@ATL@@@ATL@@@ATL@@AAY0BAF@$$CBD@Z)
我从上述消息中了解到,模板化运算符已正确实例化,并且它包含对 _fmt() 方法的调用,但是链接器找不到该方法。
但是_fmt() 是包含在一个正在被编译和喜欢的.cpp文件中,实际上构造函数也在那里定义并且链接器没有抱怨它。
我发现解决此问题的唯一方法是将_fmt() 代码放在类定义主体的头文件中,这相当难看。
有什么想法吗?
【问题讨论】:
-
第一个跳入我脑海的也是最明显的想法是:在实现文件中,您是否将其定义为
CString MyClass::_fmt(...)而不是CString _fmt(...)?除此之外,没有看到_fmt是如何定义的,我什么都没有。 -
我做了,我检查了三次。但是现在我已经仔细检查了错误并且没有加起来:使用的 CString 模板似乎使用了与有效编译的不同的特征类。在目标文件中,我得到一个名为:
?_fmt@MyClass@@AAA?AV?$CStringT@DV?$StrTraitMFC@DV?$ChTraitsCRT@D@ATL@@@@@ATL@@PBDZZ的符号,它分解为:private: class ATL::CStringT<char,class StrTraitMFC<char,class ATL::ChTraitsCRT<char> > > __cdecl MyClass::_fmt(char const *,...)注意它是如何使用StrTraitMFC而不是ATL::StrTraitATL。我猜是标题不匹配。
标签: c++ visual-studio-2010 templates unresolved-external