18

我正在继承一个类,我想调用它的一个构造函数。但是,在调用它之前,我必须处理一些东西(不需要任何基类)。有什么办法我可以稍后调用它而不是在初始化列表中调用它?我相信这可以在 Java 和 C# 中完成,但我不确定 C++。

我需要在构造函数上传递的数据以后不能重新分配,所以我不能只调用一个默认构造函数并在以后对其进行初始化。

4

6 回答 6

32

有什么办法我可以稍后调用它而不是在初始化列表中调用它?

你不能。必须在初始化列表中调用基类构造函数,并且必须首先调用它。

实际上,如果您在此处省略它,编译器只会隐式添加调用。

我相信这可以在 Java 和 C# 中完成,但我不确定 C++。

C# 和 Java 都不允许这样做。

但是,您可以做的是调用一个方法作为基类构造函数调用的参数。然后在构造函数之前处理它:

class Derived {
public:
    Derived() : Base(some_function()) { }

private:
    static int some_function() { return 42; }
};
于 2010-09-29T11:19:06.087 回答
14

正如几个回答的人所说,您不能延迟基类构造函数的调用,但Konrad 给出了一个很好的答案,可以很好地解决您的问题。但是,这确实有其缺点(例如,当您需要使用其计算共享中间结果的值来初始化多个函数时),所以为了完整起见,这是解决固定初始化顺序问题的另一种方法,通过使用它。

鉴于初始化的固定顺序,如果您可以控制派生类(以及您将如何摆弄它的一个 ctor?),您可以潜入一个私有基础,以便在另一个之前初始化它基数,然后可以使用私有基数的已计算值对其进行初始化:

class my_dirty_little_secret {
  // friend class the_class;
public: 
  my_dirty_little_secret(const std::string& str)
  {
    // however that calculates x, y, and z from str I wouldn't know
  }
  int x;
  std::string y;
  float z;
};

class the_class : private my_dirty_little_secret // must be first, see ctor
                , public the_other_base_class {
  public:
    the_class(const std::string str)
      : my_dirty_little_secret(str)
      , the_other_base_class(x, y, z)
    {
    }
  // ...
};

该类my_dirty_little_secret是一个私有基础,因此用户the_class无法使用它,它的所有内容也是私有的,明确的友谊只授予the_class对它的访问权限。但是,由于它在基类列表中列在第一位,因此它会可靠地构造在 之前the_other_base_class,因此无论它计算什么都可以用来初始化它。
基类列表中的一个很好的注释有望防止其他人通过重构来破坏事物。

于 2010-09-29T12:57:09.450 回答
0

恕我直言,我认为不可能以您提到的方式推迟调用基类构造函数。

于 2010-09-29T11:21:11.403 回答
0

哇,我们都曾经年轻过。这个答案不起作用,所以不要使用它。出于历史目的而留下的内容。

如果您可以完全控制基类,我建议您添加一个受保护的方法来进行类初始化,使其成为虚拟,并在调用其基类之前将您的派生类实现细节放入其中:

class Base
{
public:
    Base()
    {
        Initialize();
    }
protected:
    virtual void Initialize()
    {
        //do initialization;
    }
};

class Derived : Base
{
public:

    Derived() : Base()
    {
    }
protected:
    virtual void Initialize()
    {
        //Do my initialization
        //call base
        Base::Initialize();
    }
};
于 2010-09-29T11:24:39.160 回答
0

根据@Konrad 的建议,另一种选择是使用静态方法来构造对象,例如:

class Derived {
public:
    Derived(int p1, int p2, int p3) : Base(p1, p2) { }

    static Derived* CreateDerived(int p3) { return new Derived(42, 314, p3); }
};

我发现这在从库中扩展类并有多个要覆盖的参数时很有用。您甚至可以将构造函数设为私有

于 2020-12-24T04:25:12.053 回答
-2
struct base{
   base(int x){}
};

struct derived : base{
   derived(int x) : base(x){}
};

这就是在 C++ 中从派生类的初始化列表中调用基类构造函数的方式。

于 2010-09-29T11:19:13.903 回答