类继承调用不同的构造函数

发布于 2025-01-08 18:49:03 字数 436 浏览 0 评论 0原文

嘿,我有一个 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()’

hei i have a c++03 class with a simple constructor that take an integer. And a derived class with serialization methods that should take a filename as a constructor, load the integer from it, and then call the first constructor.

class A {
public:
    A(int foo);
}

and a derived class:

class XmlableA : public A {
public:
    XmlableA(int foo);

    XmlableA(string xmlfilename) {
        //load foo from xml
        // call A::A(foo)
    }
}

i tried some different solution but every time i get

no matching function for call to ‘A::A()’

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

薄暮涼年 2025-01-15 18:49:03

几乎所有答案都是相同的,所以我会建议一个不同的解决方案,我个人更喜欢它。

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);

Almost all answers are same, so I would suggest a different solution, which I would prefer personally.

Define a static member function Create as:

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);
    }
};

Usage:

XmlableA xmlable = XmlableA::Create(xmlFile);
℉絮湮 2025-01-15 18:49:03

初始化它,如下所示:

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)) {
  }

Initialize it, like so:

XmlableA(int foo) : A(foo) {}

You may also consider:

private:
  static int LoadXML(const string& xmlfilename) {
    int ret = ...; << load here
    return ret;
  }

public:
  XmlableA(string xmlfilename) : A(LoadXML(xmlfilename)) {
  }
够钟 2025-01-15 18:49:03

在 C++ 中,基类是在子类之前构造的,因此您将无法执行此操作。您可以创建一个 Factory 来获取文件名并根据该文件中的内容创建一个对象。

示例:

class XmltableAFactory {
public:
    static XmltableAFactory build(string xmlfilename) {
        // read int foo from xmlfilename
        return XmltableAFactory(foo);
    }
};

然后这样称呼它:

XmltableA myObj = XmltableAFactory::build(filename);

有几件事需要注意。

  1. 这意味着您将不需要 XmltableA 类中的 string xmlfilename 构造函数,因为如上所述,在调用基类的构造函数之前您无法知道 foo。
  2. 您可以选择按值或按指针从工厂返回。编译器可能会优化按值返回,因为您正在创建对象并在同一行上返回它。然而,通常知道通过指针返回速度更快,但您必须创建一个新对象,然后确保在使用完毕后删除它。
  3. 如果你不想浪费内存,可以看看 boost 的 auto_ptrshared_ptr

In C++ the Base class is constructed BEFORE the Child class, so you will not be able to do this. You could make a Factory that takes a filename and creates an object based on what is in that file.

Example:

class XmltableAFactory {
public:
    static XmltableAFactory build(string xmlfilename) {
        // read int foo from xmlfilename
        return XmltableAFactory(foo);
    }
};

And then call it like so:

XmltableA myObj = XmltableAFactory::build(filename);

There are a few things to note.

  1. This means that you will not need the string xmlfilename cosntructor in the XmltableA class because as discussed above, you cannot know foo before the base class's constructor is called.
  2. You can either choose to return from the factory by value or by pointer. The compiler might optimize the return by value because you are creating the object and returning it on the same line. However, return by pointer is usually known to be faster, but you'll have to create a new object and then make sure to delete it when you're done with it.
  3. If you don't want to muck about with memory, take a look at boost's auto_ptr and shared_ptr.
少女净妖师 2025-01-15 18:49:03

如果你想在调用 A::A(int) 之前做一些事情,你最终不得不破解,比如

int XmlableA::f(string filename) { /* load foo from xml */; return foo; }
XmlableA(string xmlfilename) : A(f(filename)) {}

If you want to do something before the call to A::A(int), you end up having to hack, something like

int XmlableA::f(string filename) { /* load foo from xml */; return foo; }
XmlableA(string xmlfilename) : A(f(filename)) {}
稚气少女 2025-01-15 18:49:03

好的,所以第一个很简单:

XmlableA::XmlableA(int foo) : A(foo)
{
}

第二个需要执行类似于

XmlableA(string xmlfilename) : A(fooFromXML(xmlfilename))
{
}

我们可以实现的操作,

class XmlableA : public A
{
    static int fooFromXML(string filename);

public:
    // ...

请注意 fooFromXML,它加载 XML 文件并返回您需要的整数,必须 是静态的,因为当我们调用它时,我们还没有一个 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

OK, so the first one is easy:

XmlableA::XmlableA(int foo) : A(foo)
{
}

The second one requires doing something like

XmlableA(string xmlfilename) : A(fooFromXML(xmlfilename))
{
}

which we can implement as

class XmlableA : public A
{
    static int fooFromXML(string filename);

public:
    // ...

Note that fooFromXML, which loads the XML file and returns the integer you need, must be static, because when we call it we don't yet have an XmlableA instance to invoke it on.


For multiple arguments (and as a general design), the factory is probably best: if you're wedded to the constructor model and don't care about efficiency, you can do:

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))
    {
    }

if you're concerned about parsing the XML file repeatedly, and don't care about re-entrancy, you can "memoize" xFromXML by having it cache state in a static member.

梦断已成空 2025-01-15 18:49:03

如果您的类 A 没有默认构造函数,则必须在派生类的初始化列表中显式调用构造函数。 XmlableA(string fn) : A(readIntegerFromFile(fn)) {}

但是,您应该考虑将序列化“外包”到一个单独的类中。例如,如果您有一个 A 类型的对象并且现在想要序列化它,会发生什么?您不能,因为您只能序列化 XmlableA。此外,如果您的客户决定不再需要 XML 序列化,而是需要 Yaml 或某种专有格式,会发生什么情况?您将必须更改所有代码。

If your class A does not have a default constructor you have to explicitly call a constructor in the initialization list of your derived class. XmlableA(string fn) : A(readIntegerFromFile(fn)) {}.

However, you should think about "outsourcing" the serialization into a separate class. E.g. what would happen if you have an object of type A and now you want to serialize it? You couldn't because you can only serialize a XmlableA. Furthermore, what would happen if your client decides that he no longer wants a XML serialization but Yaml or some proprietary format? You would have to change all your code.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文