如何在c++中重新初始化基类
how to reinitialize base class in c++
我有派生类和基类。在派生类的构造函数中,我必须使用基类的基本构造函数。然后,我想用不同的基类构造器重新构造基类:
class A
{
public:
int a, b;
}
class B : public A
{
B() : A()
{
...
//do some calculations to calculate a and b and then
//re-construct class A with the right values.
A(a,b) <--- ????
}
}
怎么做呢
构造函数是用来创建对象的。因此它们只使用一次。您应该创建一个方法来进行初始化,并从构造函数调用该方法。
您可以在class A
中提供复制和/或移动赋值操作。
class A
{
public:
int a, b;
// Copy assignment operator
A& operator=(const A& rhs) {
if(this == &rhs) return *this;
a = rhs.a; b = rhs.b;
return *this;
}
// ...
};
之后,你可以使用模式
重新初始化它BaseClass::operator=(BaseClass(a,b));
在你的例子中是
A::operator=(A(a,b));
如果你的类是一个聚合,或者有一个隐式定义的复制构造函数,你应该使用它们(你不必自己定义),并使用与上面相同的重新初始化模式。
正如其他人已经指出的,您只能在当前构造函数的初始化列表中调用继承的构造函数,或者(在c++ 11中)委托给当前类的其他构造函数。这是唯一可以初始化类的地方。
<标题> init方法在某些情况下,添加init()
方法是有意义的,它会重新初始化类的部分。这称为两阶段初始化。您可以在一些窗口管理api中找到它。
init()
中初始化的。您必须(必须,必须!)初始化这两个部分的方式使对象处于一致的状态——in绝不能处于无效状态。作为经验法则:如果对象是(由c'tor)创建的,那么析构函数调用必须始终是可能的。具体来说:不要让指针和句柄到处都是随机值。
class ChildWindow : Compontent {
shared_ptr<Component> parent_; // builds the component hierarchy
Component[] children_; // child cp'nts, unknown during c'tor
size_t nchildren_; // ...use e vector in real code!
public:
ChildWindow(chared_ptr<>Component> parent)
: parent_(parent),
children(nullptr), nchildren(0) // MUST initialize
{}
void addChild(Component *child) { /*... change children_ ...*/ }
void init() {
if(nchildren > 0) { /* ...throw away old ... */ }
children_ = new Component[...];
// ... init children_ with nulls
}
};
这只是一个粗略的想法,您可以使用两阶段初始化。
<标题>包装h1> 果你真的只需要重新初始化所有东西,一个技术上的解决方案可能是使用一个简单的包装器类来包装你的真实对象:class WindowWrapper {
Window *window_;
public:
WindowWrapper() : window_(nullptr) {}
void reset() { delete window_; window_ = nullptr; }
Window& get() { return *window_; }
Window& operator*() { return get(); }
}
…随便打出来的,可能有错误。这就是为什么在c++ 11中已经有了这样一个包装器:
unique_ptr<Window> win { new Window{parent, "title"} };
// ..use win...
win.reset( new Window{otherparent, "other title"} };
如果这个unique_ptr
不够,你可以把它放在上面的包装。
作为旁注,解释你写的代码的作用:
B::B() : A() {
A(a,b); // <--- ????
}
当你输入"????"行时,你创建了一个A
类型的*临时对象,它在函数退出时消失。不调用当前对象的析构函数。
为什么要创建一个临时对象?你可以写
A a(a,b);
作为语句,您将获得类A
的新实例a
,该实例由带有两个参数的a c'构造。这个a
可以在另一个函数调用中使用,比如func(a);
。但是您可以省去显式变量a
,只需省略它的名称:
func(A(a,b));
用A
类的未命名("临时")对象调用func
,该对象在语句结束时消失(即;
)。
这些临时对象可以创建为表达式。因为每个表达式也是一个语句
A(a,b);
是一个有效的语句——创建一个临时对象,它立即消失。
标题>标题>标题>除非在初始化列表中,否则不能调用父类的构造函数。如果要在不同构造的a对象上使用操作,则必须使用复合而不是继承。如果一个方法改变了一个已经构造的对象,它就不是构造函数。因此,要么用新构造的对象替换对象(而不是更改对象),要么使用非构造函数方法。
将计算a和b的代码放入一个方法中,并在初始化列表中使用它:
class A {
public:
A(int a, int b): a_(a), b_(b) {}
};
class B : public A
{
public:
B(): A(B::computeA(), B::computeB()) {}
private:
static int computeA();
static int computeB();
};
我将这些方法设置为静态,以防止使用部分初始化的对象。
尽管我不得不说这个问题和例子听起来像你在使用继承来重用实现。在这种情况下,不应该使用继承,而应该使用复合,并用成员对象替换继承。
- C++初始化基类
- C++17 使用驱动类常量作为基类构造函数的参数来初始化基类构造函数
- 我是否需要在虚拟继承类的构造函数中初始化基类以解决菱形继承问题?
- 使用成员的地址初始化基类是否合法?
- 初始化基类成员 (c++) 的首选方法
- 类的构造函数必须显式初始化基类
- OOP - 抽象类类型,初始化基类和派生类中的变量
- 初始化基类和派生类中的类成员变量
- 为什么 C++ 的创建者决定使用构造函数初始值设定项列表来初始化基类?
- 通过drived类模板值通过基类构造器初始化基类数组成员变量
- 使用派生的[C++]生成的参数初始化基类
- C++ 在派生类中初始化基类的 const int?
- C++是否要求您从其派生类初始化基类成员
- 通过 CRTP 使用派生类变量初始化基类静态常量变量
- 初始化基类,派生类的构造函数中没有默认构造函数
- 我可以调用一个虚拟函数来初始化基类子对象吗
- 如何初始化基类构造函数的向量
- 初始化基类
- 在派生类的构造函数的主体中初始化基类成员变量
- 初始化基类的引用成员