【发布时间】:2011-04-18 18:37:14
【问题描述】:
我正在继承一个类,我想调用它的一个构造函数。但是,在调用它之前,我必须处理一些东西(不需要任何基类)。有什么办法我可以稍后调用它而不是在初始化列表中调用它?我相信这可以在 Java 和 C# 中完成,但我不确定 C++。
我需要在构造函数上传递的数据以后不能重新赋值,所以我不能只是调用一个默认构造函数并在以后初始化它。
【问题讨论】:
标签: c++ constructor delayed-execution
我正在继承一个类,我想调用它的一个构造函数。但是,在调用它之前,我必须处理一些东西(不需要任何基类)。有什么办法我可以稍后调用它而不是在初始化列表中调用它?我相信这可以在 Java 和 C# 中完成,但我不确定 C++。
我需要在构造函数上传递的数据以后不能重新赋值,所以我不能只是调用一个默认构造函数并在以后初始化它。
【问题讨论】:
标签: c++ constructor delayed-execution
有什么方法可以让我稍后调用它而不是在初始化列表中调用它?
不,你不能。基类构造函数必须在初始化列表中调用,而且必须先调用。
实际上,如果您在此处省略它,编译器只会隐式添加调用。
我相信这可以在 Java 和 C# 中完成,但我不确定 C++。
C# 和 Java 都不允许这样做。
然而,您可以做的是调用基类构造函数调用的方法作为参数。然后在构造函数之前处理它:
class Derived {
public:
Derived() : Base(some_function()) { }
private:
static int some_function() { return 42; }
};
【讨论】:
super(...) 完成的,但我现在注意到它必须是第一行.
this指针。
this 指针还不存在,而这是计算成员变量的位置所需要的。
正如几个回答的人所说,您不能延迟基类构造函数的调用,但Konrad has given a good answer 可能会很好地解决您的问题。但是,这确实有其缺点(例如,当您需要使用其计算共享中间结果的值来初始化多个函数时),所以为了完整起见,这是解决固定初始化顺序问题的另一种方法,使用 它。
鉴于初始化的固定顺序,如果您可以控制派生类(否则您将如何摆弄它的一个 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 之前构造它,因此无论它计算什么都可以用来初始化它。
基类列表中的一个很好的注释有望防止其他人通过重构来破坏事物。
【讨论】:
恕我直言,我认为不可能以您提到的方式推迟调用基类构造函数。
【讨论】:
哇,我们都曾经年轻过。这个答案不起作用,所以不要使用它。内容留作历史用途。
如果您可以完全控制基类,我建议您添加一个受保护的方法来进行类初始化,使其成为虚拟,并在调用其基类之前将您的派生类实现细节放入其中:
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();
}
};
【讨论】:
根据@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); }
};
我发现这在从库中扩展类并需要覆盖多个参数时很有用。 你甚至可以让构造函数private
【讨论】:
struct base{
base(int x){}
};
struct derived : base{
derived(int x) : base(x){}
};
这就是在 C++ 中从派生类的初始化列表中调用基类构造函数的方式。
【讨论】: