我有一个以下问题:
我想实现以下类的结构:
IParser.h
#ifndef IPARSER_H
#define IPARSER_H
#include "json.h"
class IParser
{
public:
template <typename T>
json::Object Parse(const T&, json::Object);
};
#endif // IPARSER_H
HTMLParser.h
#ifndef HTMLPARSER_H
#define HTMLPARSER_H
#include <iostream>
#include "IParser.h"
class HTMLParser : public IParser
{
public:
HTMLParser();
~HTMLParser();
json::Object Parse(std::string const&, json::Object&);
};
#endif
HTMLParser.cpp
#include "HTMLParser.h"
HTMLParser::HTMLParser()
{
std::cout << "constructed" << std::endl;
}
HTMLParser::~HTMLParser()
{
std::cout << "destructed" << std::endl;
}
json::Object HTMLParser::Parse(std::string const& data, json::Object& object)
{
// do something
return json::Object();
}
但是当我想要构建它时,它会抛出这个错误:
error LNK2019: unresolved external symbol "public: class json::Object __thiscall
IParser::Parse<class std::basic_string<char,struct std::char_traits<char>,class
std::allocator<char> > >(class std::basic_string<char,struct std::char_traits<char>,class
std::allocator<char> > const &,class json::Object)" (??$Parse@V?$basic_string@DU?
$char_traits@D@std@@V?$allocator@D@2@@std@@@IParser@@QAE?AVObject@json@@ABV?$basic_string@DU?
$char_traits@D@std@@V?$allocator@D@2@@std@@V12@@Z) referenced in function _main
知道可能出现什么问题吗? 基本上我想创建带有模板化函数的接口类,子类将指定并实现它。
任何帮助将不胜感激。感谢。
答案 0 :(得分:1)
首先让我们看看错误试图告诉你什么,而不是非常雄辩。错误来自链接器
error LNK2019: unresolved external symbol
所以编译器对你的代码没问题,只是它为链接器找不到的符号创建了一个依赖项。符号是
“public:class json :: Object __thiscall IParser :: Parse&lt; class std :: basic_string&lt; char,struct std :: char_traits&lt; char&gt ;, class std :: allocator&lt; char&gt;&gt;&gt; ;(类std :: basic_string&lt; char,struct std :: char_traits&lt; char&gt;,class std :: allocator&lt; char&gt;&gt; const&amp;,class json :: Object)“blah blah mangled signature。 ..在函数_main
中引用
这不是非常易读,让我们通过这种替换使其更具可读性
使用string = class std :: basic_string&lt; char,struct std :: char_traits&lt; char&gt;,类std :: allocator&lt; char&gt; &GT;
现在错误是
“public:class json :: Object __thiscall IParser :: Parse&lt; string&gt;(class string const&amp;,class json :: Object)”
这就是说在函数_main中你正在调用函数Parse<string>
,它是类Iparser
的成员,有两个参数,一个对字符串的引用和一个json: :按值对象。
但是等等,你说,我确实在派生类中提供了一个定义!
json::Object HTMLParser::Parse(std::string const& data, json::Object& object)
{
// do something
return json::Object();
}
这有三个原因导致它无法按预期运行:
Parse
成员函数,这样如果你使用指向派生类HTMLParser
的指针调用它,你的派生类成员函数将被调用。如果您尝试使用指向基类Parse
的指针调用IParser
成员函数,则编译器会生成对该函数的调用(它们不同!)并且您尚未定义它。那么当你使用指向基类Parse
的指针调用它时,你怎么做才能让编译器调用派生类HTMLParser::Parse
的{{1}}成员函数?为此,您需要了解polymorphism and virtual inheritance。好吧,你说,我将使IParser
基类的Parse
成员函数为纯虚拟,并强制每个派生类提供一个定义。那是你遇到第三个问题的时候。解决尝试使用泛型编程(模板)和面向对象编程(继承)这一问题的一种方法是使用一种称为类型擦除的模式,它在某些情况下有用...你可以在<强> On the Tension Between Object-Oriented and Generic Programming in C++ and What Type Erasure Can Do About It 强>
答案 1 :(得分:0)
让整个班级成为模板:
template <typename T>
class IParser
{
public:
json::Object Parse(const T&, json::Object);
};
然后您的子类可以继承模板化类:
class HTMLParser : public IParser<std::string>
请注意,从不同模板版本继承的类不会共享公共基类,因此您可能需要:
class IParserBase
{
//...
};
template <typename T>
class IParser : public IParserBase
{
public:
json::Object Parse(const T&, json::Object);
};