简体   繁体   English

稍后在 C++ 中调用基类构造函数(不在初始化列表中)

[英]Call a base class constructor later (not in the initializer list) in C++

I'm inheriting a class and I would like to call one of its constructors.我正在继承一个类,我想调用它的构造函数之一。 However, I have to process some stuff (that doesn't require anything of the base class) before calling it.但是,在调用它之前我必须处理一些东西(不需要任何基类的东西)。 Is there any way I can just call it later instead of calling it on the initializer list?有什么办法可以稍后调用它而不是在初始化列表中调用它? I believe this can be done in Java and C# but I'm not sure about C++.我相信这可以在 Java 和 C# 中完成,但我不确定 C++。

The data that I need to pass on the constructor can't be reassigned later, so I can't just call a default constructor and initialize it later.我需要在构造函数上传递的数据不能在以后重新分配,所以我不能只调用一个默认构造函数并稍后对其进行初始化。

Is there any way I can just call it later instead of calling it on the initializer list?有什么办法可以稍后调用它而不是在初始化列表中调用它?

No, you cannot.不,你不能。 The base class constructor must be called in the initializer list, and it must be called first.必须在初始化列表中调用基类构造函数,并且必须首先调用它。

In fact, if you omit it there, the compiler will just add the call implicitly.事实上,如果你在那里省略它,编译器只会隐式地添加调用。

I believe this can be done in Java and C# but I'm not sure about C++.我相信这可以在 Java 和 C# 中完成,但我不确定 C++。

Neither C# nor Java allow this either. C# 和 Java 都不允许这样做。

What you can do, however, is call a method as an argument of the base class constructor call.但是,您可以做的是调用一个方法作为基类构造函数调用的参数 This is then processed before the constructor:然后在构造函数之前处理它:

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

private:
    static int some_function() { return 42; }
};

As was said by several people answering, you cannot delay the invocation of a base class constructor, but Konrad has given a good answer that might well solve your problem.正如回答的几个人所说,您不能延迟基类构造函数的调用,但Konrad 给出了一个很好的答案,可以很好地解决您的问题。 However, this does have its drawbacks (for example, when you need to initialize several functions with values whose calculations share intermediate results), so just to be complete, here's another way of solving the problem of fixed initialization order, by using it.但是,这确实有其缺点(例如,当您需要使用其计算共享中间结果的值来初始化多个函数时),所以为了完整起见,这是解决固定初始化顺序问题的另一种方法,通过使用它。

Given the fixed order of initialization, if you have control over the derived class (and how else would you come to fiddle with one of its ctors?), you can sneak in a private base so that it is going to be initialized before the other base, which can then be initialized with the private base's already calculated values:给定初始化的固定顺序,如果您可以控制派生类(以及您将如何摆弄它的一个 ctors?),您可以潜入一个私有基类,以便它在另一个类之前被初始化基,然后可以使用私有基已经计算的值进行初始化:

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)
    {
    }
  // ...
};

The my_dirty_little_secret class is a private base so that users of the_class cannot use it, all of its stuff is private, too, with explicit friendship granting only the_class access to it. my_dirty_little_secret类是私有基础,因此the_class用户无法使用它,它的所有内容也是私有的,显式友谊仅授予the_class访问权限。 However, since it's listed first in the base class list, it will reliably be constructed before the_other_base_class , so whatever it calculates can be used to initialize that.但是,由于它首先列在基类列表中,因此它将在the_other_base_class之前可靠地构造,因此无论它计算什么,都可以用来初始化它。
A nice comment at the base class list hopefully prevents from others breaking things by refactoring.基类列表中的一个很好的注释有望防止其他人通过重构破坏事物。

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

Wow, we were all young once.哇,我们都曾经年轻过。 This answer won't work, so don't use it.这个答案不起作用,所以不要使用它。 Content left for historical purposes.内容留作历史用途。

If you have full control over the base class, I'd recommend adding a protected method to do the class initialization, make it virtual, and put the your derived class implementation details in it before it calls its base:如果您可以完全控制基类,我建议添加一个受保护的方法来进行类初始化,使其成为虚拟的,并在调用其基类之前将派生类的实现细节放入其中:

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

Another option, based on the suggestion from @Konrad is to have a static method to construct the object, eg:根据@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); }
};

Ive found this useful when extending a class from a library and having multiple parameters to override.我发现这在从库中扩展类并具有多个要覆盖的参数时很有用。 You can even make the constructor private您甚至可以将构造函数设为私有

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

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

This is how base class constructors are invoked in C++ from the initialization list of derived class.这就是在 C++ 中从派生类的初始化列表中调用基类构造函数的方式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 任何在构造函数C ++之前证明初始化器列表调用的示例 - Any Example that Prove Initializer List Call before Constructor C++ C++派生类构造函数调用基类构造函数错误 - C++ derived class constructor call base class constructor errors 在C ++中派生类构造函数之后调用基类构造函数 - Call base class constructor after the derived class constructor in C++ c++ 中派生的 class 构造函数中的动态基 class 构造函数调用 - dynamic base class constructor call in derived class constructor in c++ C ++为类模板提供初始化列表构造函数 - C++ Supply initializer-list constructor for class template C ++:struct / class中的构造函数与初始化列表 - C++: Constructor versus initializer list in struct/class 派生 class 构造函数初始值设定项列表中的基本 class 默认构造函数 - Base class default constructor in derived class constructor initializer list 我可以使用在初始化列表中初始化的C ++类成员,稍后在列表中吗? - Can I use C++ class members initialized in the initializer list, later in the list? 派生类的副本构造函数(C ++)的初始化列表上的基类 - Base class on the initialisation list of a derived class' copy constructor (C++) c ++具有复杂赋值的构造函数初始值设定项列表 - c++ Constructor initializer list with complex assignments
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM