hei我有一个c ++ 03类,带有一个带整数的简单构造函数。一个带有序列化方法的派生类,它应该将文件名作为构造函数,从中加载整数,然后调用第一个构造函数。
class A {
public:
A(int foo);
}
和派生类:
class XmlableA : public A {
public:
XmlableA(int foo);
XmlableA(string xmlfilename) {
//load foo from xml
// call A::A(foo)
}
}
我尝试了一些不同的解决方案,但每次我都
no matching function for call to ‘A::A()’
答案 0 :(得分:4)
初始化它,如下:
XmlableA(int foo) : A(foo) {}
您也可以考虑:
private:
static int LoadXML(const string& xmlfilename) {
int ret = ...; << load here
return ret;
}
public:
XmlableA(string xmlfilename) : A(LoadXML(xmlfilename)) {
}
答案 1 :(得分:4)
几乎所有的答案都是一样的,所以我建议采用不同的解决方案,我个人更愿意。
将static
成员函数Create
定义为:
class XmlableA : public A {
public:
XmlableA(int foo);
//static member function
static XmlableA Create(string const & xmlfilename)
{
//load foo from xml
int foo = /*load from file*/;
return XmlableA(foo);
}
};
用法:
XmlableA xmlable = XmlableA::Create(xmlFile);
答案 2 :(得分:3)
在C ++中,Base类是在Child类之前构造的,因此您将无法执行此操作。您可以创建一个Factory,它接受一个文件名并根据该文件中的内容创建一个对象。
示例:
class XmltableAFactory {
public:
static XmltableAFactory build(string xmlfilename) {
// read int foo from xmlfilename
return XmltableAFactory(foo);
}
};
然后这样称呼它:
XmltableA myObj = XmltableAFactory::build(filename);
有几点需要注意。
string xmlfilename
类中的XmltableA
cosntructor,因为如上所述,在调用基类的构造函数之前,您无法知道foo。new
对象,然后确保在完成后delete
。auto_ptr
和shared_ptr
。答案 3 :(得分:2)
如果你想在致电A::A(int)
之前做某事,你最终不得不进行攻击,比如
int XmlableA::f(string filename) { /* load foo from xml */; return foo; }
XmlableA(string xmlfilename) : A(f(filename)) {}
答案 4 :(得分:2)
好的,所以第一个很容易:
XmlableA::XmlableA(int foo) : A(foo)
{
}
第二个需要做类似
的事情XmlableA(string xmlfilename) : A(fooFromXML(xmlfilename))
{
}
我们可以实现
class XmlableA : public A
{
static int fooFromXML(string filename);
public:
// ...
请注意fooFromXML
加载XML文件并返回所需的整数,必须是静态的,因为当我们调用它时,我们还没有{{1}实例调用它。
对于多个参数(以及作为一般设计),工厂可能是最好的:如果您已经与构造函数模型结合并且不关心效率,那么您可以这样做:
XmlableA
如果您担心重复解析XML文件而不关心重新入侵,可以通过将其缓存状态置于静态成员中来“memoize”class XmlableA : public A
{
static int intFromXML(char const *varname, string const &filename);
public:
XmlableA(string const &xmlfilename)
: A(intFromXML("foo", xmlfilename), intFromXML("bar", xmlfilename))
{
}
。
答案 5 :(得分:1)
如果您的A类没有默认构造函数,则必须在派生类的初始化列表中显式调用构造函数。 XmlableA(string fn) : A(readIntegerFromFile(fn)) {}
。
但是,您应该考虑将序列化“外包”到一个单独的类中。例如。如果你有一个A
类型的对象,现在想要序列化它会发生什么?你不能,因为你只能序列化XmlableA
。此外,如果您的客户决定他不再需要XML序列化但是Yaml或某些专有格式,会发生什么?您必须更改所有代码。