Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/135.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何在C+中将方法结果作为参数传递给基类构造函数+;?_C++_Inheritance_Constructor_Initialization_Composition - Fatal编程技术网

C++ 如何在C+中将方法结果作为参数传递给基类构造函数+;?

C++ 如何在C+中将方法结果作为参数传递给基类构造函数+;?,c++,inheritance,constructor,initialization,composition,C++,Inheritance,Constructor,Initialization,Composition,我一直在努力实现这样的目标: class Base { public: Base(string S) { ... }; } class Derived: Base { public: int foo; string bar() { return stringof(foo); // actually, something more complex }; Derived(int f) : foo(f), Base(bar()) { }

我一直在努力实现这样的目标:

class Base
{
  public:

  Base(string S) 
  {
  ...
  };
}

class Derived: Base
{
public:
  int foo;
  string bar()
  {
    return stringof(foo); // actually, something more complex
  };

  Derived(int f) : foo(f), Base(bar()) 
  {
  };
}
Derived(int f) : Base(stringof(f)), foo(f) {}
现在,这并不是我想要的,因为在初始化foo之前,在派生构造函数中调用bar()

我考虑添加一个类似于bar()的静态函数,它将foo作为一个参数,并在初始化列表中使用它,但我想问一下是否有其他技术可以帮助我摆脱这个问题

编辑:感谢您的反馈-以下是我将如何处理静态功能。不确定静态和非静态函数之间的重载是否太聪明,但是

class Derived: Base
{
public:
  int foo;

  static string bar(int f)
  {
    return stringof(f); // actually, something more complex
  }

  string bar()
  {
    return bar(foo); 
  };

  Derived(int f) :  Base(bar(f)) , foo(f)
  {
  };
}
是的,使用以foo为参数并返回字符串的函数(静态类方法或常规函数)是一个很好的解决方案。您可以从派生::bar调用相同的函数,以防止代码重复。因此,您的构造函数将如下所示:

class Base
{
  public:

  Base(string S) 
  {
  ...
  };
}

class Derived: Base
{
public:
  int foo;
  string bar()
  {
    return stringof(foo); // actually, something more complex
  };

  Derived(int f) : foo(f), Base(bar()) 
  {
  };
}
Derived(int f) : Base(stringof(f)), foo(f) {}
我将对基构造函数的调用放在列表的第一位,以强调初始化发生的顺序。初始化器列表的顺序无效,因为所有类成员都是按照它们在类主体中声明的顺序初始化的

这是一个非常干净的解决问题的方法。但是,如果您仍然想权衡替代方案,那么考虑派生类和基类之间的关系而不是继承使用:

class Base {
public:
    Base(string S) {  ...  }
    void bat() { ... }
};

class Derived {
    Base *base;
    int foo;

public:
    Derived(int f) : base(NULL), foo(f) {
        base = new Base(bar());
    }
    ~Derived() {
        delete base;
    }

    string bar() {
        return stringof(foo); // actually, something more complex
    }

    void bat() {
        base->bat();
    }
};

你需要考虑你的具体情况的利弊。通过持有对Base的引用,您可以更好地控制初始化顺序。

我也一直想这样做,但最终还是放弃了。
任何合适的函数调用都可以用作Base()的参数。

另一个选项是向Base添加另一个构造函数,该构造函数接受int并转换为字符串本身。

您只能在初始值设定项列表中调用静态函数。您在代码中使用它的方式:

class Derived: Base
{
public:
  int foo;
  string bar()
  {
    return stringof(foo); // actually, something more complex
  };

  Derived(int f) : foo(f), Base(bar()) 
  {
  };
}
仍将首先初始化Base,然后初始化foo。在构造函数初始值设定项列表中写入内容的顺序在任何方面都不重要。它将始终按以下顺序构造:

  • 首先,所有虚拟基类
  • 然后按非虚拟基类在“基类”列表中出现的顺序显示它们
  • 然后按类定义中定义的顺序排列所有成员对象 因此,最终使用未初始化的值调用
    stringof
    。这个问题在一年内就解决了。还要注意,在所有基类的所有构造函数初始值设定项完成之前调用任何非静态成员函数都是未定义的行为

    但是,调用静态函数完全可以:

    class Derived: Base
    {
    public:
      int foo;
      static string bar(int f)
      {
        return stringof(f); // actually, something more complex
      };
    
      Derived(int f) : Base(bar(f)), foo(f)
      {
      };
    }
    

    基类构造函数总是在初始化派生类的其他成员之前被调用;编译器应该警告您初始值设定项的顺序错误。唯一正确的解决方案是使
    bar()
    成为一个静态方法,将
    f
    作为参数。

    构造函数用于构造对象。这意味着,在它返回之前,那里没有对象,因此调用成员函数无法可靠地工作。正如其他人所说,使用静态函数或非成员函数。

    只需将构造函数代码移动到Initialize()函数并从构造函数中调用它即可。这比静态/非静态重写或诸如此类的操作要简单得多。

    替代构造函数并不好,因为转换逻辑基本上是派生类的一部分。我猜是这样的,但这是我能想到的静态函数的唯一替代方法。严格说来不是这样,因为构造函数调用非静态方法是常见的做法,例如,“init()”。初始化列表有点不同。嗯,将其与pimpl习惯用法相结合会更好——但是组合的缺点是暴露基本方法所需的“类似蝙蝠”存根的数量。没错!我想在这种情况下,你会坚持A计划,就是因为这个原因。你没有抓住重点。基类不能按照您描述的方式正确构造。