看下面的代码:
class configbase {
public:
configbase(const string& name, const string& description) : m_name(name), m_description(description) {}
virtual void configd(const string& name, const string& dec);
virtual ~configbase();
protected:
string m_name;
string m_description;
};
template<class T>
class config : public configbase {
public:
config(const string& name, const string& description) : configbase(name, description) {}
using ptr = std::shared_ptr<config>;
void bins(const T& val) {}
void configd(const string& name, const string& val) override {
m_name = name;
m_description = val;
}
};
int main(){
return 0;
}
这段代码没有问题。
但是下面的就存在问题:
class ConfigVarBase{
public:
using ptr = std::shared_ptr<ConfigVarBase>;
// 记录信息的名字和描述
ConfigVarBase(const std::string& name,
const std::string& description = "")
:m_name(name),
m_description(description)
{
// 统一转换成小写
std::transform(m_name.begin(),
m_name.end(),
m_name.begin(),
::tolower
);
}
virtual ~ConfigVarBase(){}
const std::string& getName() const {return m_name;}
const std::string& getDescription()const{return m_description;}
virtual std::string toString();//{return "";}
virtual bool fromString(const std::string& val);//{ return true;}
// 拿到信息的类型名字
virtual std::string getTypename()const;//{return "";}
protected:
std::string m_name;
std::string m_description;
};
// 根据不同的类型进行构建信息对象
template<class T>
class configvar:public ConfigVarBase{
public:
using ptr = std::shared_ptr<configvar>;
configvar(
const std::string& name,
const T& default_value,
const std::string& descriiption=""
):ConfigVarBase(name, descriiption){
m_val = default_value;
}
~configvar(){}
// 将信息转换成字符串
std::string toString()override{
try
{
return boost::lexical_cast<std::string>(m_val);
}
catch(const std::exception& e)
{
SYLAR_LOG_ERROR(SYLAR_LOG_ROOT())<<"configvar::tostring exception"
<< e.what()<<"convert:"<<typeid(m_val).name()<<"to string";
// std::cerr << e.what() << '\n';
}
return "";
}
// 将字符串转化成信息,并返回转化的结果
bool fromString(const std::string& val)override{
try
{
m_val = boost::lexical_cast<T>(val);
return true;
}
catch(const std::exception& e)
{
SYLAR_LOG_ERROR(SYLAR_LOG_ROOT())<<"configvar::fromstring exception"
<<e.what()<<"convert:string to"<<typeid(m_val).name();
}
return false;
}
T getValue()const{return m_val;}
std::string getTypename()const override{
// 对T变成字符串
return "";
}
void setValue(const T& value)const{m_val = value;}
private:
T m_val;
};
如果说我将基类中的虚函数进行空实现,此时就没有问题。第一段代码没有做成动态库。第二个是做成了动态库的代码。
错误信息:
Undefined symbols for architecture arm64:
"typeinfo for sylar::ConfigVarBase", referenced from:
std::__1::shared_ptr<sylar::configvar<int> > std::__1::dynamic_pointer_cast[abi:v15006]<sylar::configvar<int>, sylar::ConfigVarBase>(std::__1::shared_ptr<sylar::ConfigVarBase> const&) in test_config.cpp.o
typeinfo for sylar::configvar<int> in test_config.cpp.o
"vtable for sylar::ConfigVarBase", referenced from:
sylar::ConfigVarBase::ConfigVarBase(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) in test_config.cpp.o
sylar::ConfigVarBase::~ConfigVarBase() in test_config.cpp.o
NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [/Users/al/Desktop/C++/workspace/bin/test_config] Error 1
make[1]: *** [CMakeFiles/test_config.dir/all] Error 2
make: *** [all] Error 2
待解决!!!