C++ 类继承调用不同的构造函数
我有一个c++03类,它有一个简单的构造函数,它接受一个整数。以及具有序列化方法的派生类,这些方法应将文件名作为构造函数,从中加载整数,然后调用第一个构造函数C++ 类继承调用不同的构造函数,c++,inheritance,constructor,C++,Inheritance,Constructor,我有一个c++03类,它有一个简单的构造函数,它接受一个整数。以及具有序列化方法的派生类,这些方法应将文件名作为构造函数,从中加载整数,然后调用第一个构造函数 class A { public: A(int foo); } 和派生类: class XmlableA : public A { public: XmlableA(int foo); XmlableA(string xmlfilename) { //load foo from xml
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()’
如果您想在调用A::Aint之前做一些事情,那么您最终必须进行黑客攻击,比如
int XmlableA::f(string filename) { /* load foo from xml */; return foo; }
XmlableA(string xmlfilename) : A(f(filename)) {}
如果您想在调用A::Aint之前做一些事情,那么您最终必须进行黑客攻击,比如
int XmlableA::f(string filename) { /* load foo from xml */; return foo; }
XmlableA(string xmlfilename) : A(f(filename)) {}
<>在C++中,基类是在子类之前构建的,所以您将不能这样做。您可以创建一个文件名,并根据该文件中的内容创建一个对象 例如:
class XmltableAFactory {
public:
static XmltableAFactory build(string xmlfilename) {
// read int foo from xmlfilename
return XmltableAFactory(foo);
}
};
然后这样称呼它:
XmltableA myObj = XmltableAFactory::build(filename);
有几件事需要注意
这意味着您将不需要XmltableA类中的字符串xmlfilename协构造函数,因为如上所述,在调用基类的构造函数之前,您无法知道foo。
您可以选择通过值或指针从工厂返回。编译器可能会优化按值返回,因为您正在创建对象并在同一行上返回它。然而,指针返回通常会更快,但您必须创建一个新对象,然后确保在完成后将其删除。
如果你不想浪费内存,可以看看boost的auto_ptr和shared_ptr。
<>在C++中,基类是在子类之前构建的,所以您将不能这样做。您可以创建一个文件名,并根据该文件中的内容创建一个对象 例如:
class XmltableAFactory {
public:
static XmltableAFactory build(string xmlfilename) {
// read int foo from xmlfilename
return XmltableAFactory(foo);
}
};
然后这样称呼它:
XmltableA myObj = XmltableAFactory::build(filename);
有几件事需要注意
这意味着您将不需要XmltableA类中的字符串xmlfilename协构造函数,因为如上所述,在调用基类的构造函数之前,您无法知道foo。
您可以选择通过值或指针从工厂返回。编译器可能会优化按值返回,因为您正在创建对象并在同一行上返回它。然而,指针返回通常会更快,但您必须创建一个新对象,然后确保在完成后将其删除。
如果你不想浪费内存,可以看看boost的auto_ptr和shared_ptr。
初始化它,如下所示:
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)) {
}
初始化它,如下所示:
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)) {
}
好的,第一个很简单:
XmlableA::XmlableA(int foo) : A(foo)
{
}
第二个需要做一些类似的事情
XmlableA(string xmlfilename) : A(fooFromXML(xmlfilename))
{
}
我们可以将其作为
class XmlableA : public A
{
static int fooFromXML(string filename);
public:
// ...
请注意,加载XML文件并返回所需整数的fooFromXML必须是静态的,因为当我们调用它时,我们还没有一个XmlableA实例来调用它
对于多个参数和一般设计,工厂可能是最好的:如果你只关注构造函数模型,而不关心效率,你可以:
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))
{
}
如果您关心重复解析XML文件,而不关心重入性,则可以通过将xFromXML缓存状态保存在静态成员中来记忆xFromXML。好的,因此第一个很简单:
XmlableA::XmlableA(int foo) : A(foo)
{
}
第二个需要做一些类似的事情
XmlableA(string xmlfilename) : A(fooFromXML(xmlfilename))
{
}
我们可以将其作为
class XmlableA : public A
{
static int fooFromXML(string filename);
public:
// ...
请注意,加载XML文件并返回所需整数的fooFromXML必须是静态的,因为当我们调用它时,我们还没有一个XmlableA实例来调用它
对于多个参数和一般设计,工厂可能是最好的:如果你只关注构造函数模型,而不关心效率,你可以:
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))
{
}
如果您关心重复解析XML文件,而不关心重入性,则可以通过将xFromXML缓存状态保存在静态成员中来记忆xFromXML。如果类a没有默认构造函数,则必须在派生类的初始化列表中显式调用构造函数。XmlableAstring fn:AreadIntegerFromFilefn{}
但是,您应该考虑将序列化外包到一个单独的类中。例如,如果您有一个类型为A的对象,并且现在要序列化它,会发生什么情况?您不能,因为您只能序列化XmlableA。此外,如果您的客户机决定不再需要XML序列化,而是Yaml或某些专有格式,会发生什么情况?您必须更改所有代码。如果您的类A没有默认构造函数,则必须在派生类的初始化列表中显式调用构造函数。XmlableAstring fn:AreadIntegerFromFilefn{} 但是,您应该考虑将序列化外包到一个单独的类中。例如,如果您有一个类型为A的对象,并且现在要序列化它,会发生什么情况?您不能,因为您只能序列化XmlableA。此外,如果您的客户机决定不再需要XML序列化,而是Yaml或某些专有格式,会发生什么情况?Y
您必须更改所有代码。几乎所有答案都是相同的,因此我建议使用不同的解决方案,我个人更喜欢这种解决方案 将静态成员函数定义为创建: 用法:
XmlableA xmlable = XmlableA::Create(xmlFile);
几乎所有的答案都是一样的,所以我会建议一个不同的解决方案,我个人更喜欢 将静态成员函数定义为创建: 用法:
XmlableA xmlable = XmlableA::Create(xmlFile);
因此,将xmlfilename传递给f.@FredLarson;哎呀。正当修正了。如果您在创建一个instance@Useless不一定非要这样,即使这样做最安全。如果不是,您必须非常小心在其中执行的操作;哎呀。正当修正了。如果您在创建一个instance@Useless不一定非要这样,即使这样做最安全。如果不是,你必须非常小心你在里面做什么。很好的解决方案!int foo只是一个例子,我有4个参数,实际上你的意思是,A::A接受多个参数,你需要从XML文件中解包它们?很好的解决方案!int foo只是一个例子,我有4个参数,实际上你的意思是,A::A接受多个参数,你需要将它们从XML文件中解压出来?@nkint 4参数到。。。或者对于XmlableA…?我认为LoadXML应该是一个私有的静态成员函数,如果其他任何类或函数都不需要它。@Nawaz:heck,把它放在命名空间{}中,那么它甚至不需要在XmlableA中。@nkint我认为除了Nawaz的一些变体之外,没有任何解决方案。@Nawaz对于生产代码来说,可见性+1是一个很好的观点。对于一个如此快速的回答,也许有点迂腐。不过-更新了,谢谢。@nkint 4参数到。。。或者对于XmlableA…?我认为LoadXML应该是一个私有的静态成员函数,如果其他任何类或函数都不需要它。@Nawaz:heck,把它放在命名空间{}中,那么它甚至不需要在XmlableA中。@nkint我认为除了Nawaz的一些变体之外,没有任何解决方案。@Nawaz对于生产代码来说,可见性+1是一个很好的观点。对于一个如此快速的回答,也许有点迂腐。不过-更新了,谢谢。如果您不需要从XmlableA派生,这是很好的。。。这只是为了证明,如果XmlableA的唯一原因是提供一个额外的构造函数,那么派生就没有什么用处。是的,到目前为止,这似乎是更好的解决方案。但是,来自@krynr的关于取消资源序列化的建议也是一个很好的主意!而且,它可以很容易地进行调整,放入静态memeber创建的ax外部类中!如果您不需要从XmlableA派生,这是很好的。。。这只是为了证明,如果XmlableA的唯一原因是提供一个额外的构造函数,那么派生就没有什么用处。是的,到目前为止,这似乎是更好的解决方案。但是,来自@krynr的关于取消资源序列化的建议也是一个很好的主意!而且,它可以很容易地进行调整,放入静态memeber创建的ax外部类中!