C++:在派生类构造函数中调用基类赋值运算符的错误形式?

Posted

技术标签:

【中文标题】C++:在派生类构造函数中调用基类赋值运算符的错误形式?【英文标题】:C++: Bad Form to Call Base Class Asssignment Operator in Derived Class Constructor? 【发布时间】:2013-06-22 23:49:19 【问题描述】:

我知道对于独立类,您应该避免在复制构造函数中调用赋值运算符。复制和交换以及将重用的代码移动到私有成员函数是轻松重用代码的两种方法。但是,最近我遇到了一个问题。代码如下:

// Derived.h
class Derived : Base 
  // bunch of fun stuff here
  // ...
  // constructor that builds a derived object from a base one
  explicit Derived(const Base& base);
  // Assignment operator for moving base class member variables into the derived one
  Derived& operator=(const Base& base);
;
// Derived.cpp
Derived::Derived(const& Base base) 
  *this = base; // use assignment operator from derived to base

Derived& Derived::operator=(const Base& base) 
  static_cast<Base>(*this) = base;  // call base class assignment operator

在这个给定的应用程序中,这一切都是有意义的,因为派生类现在可以对它刚刚从基类接收到的成员执行操作以填充对象的其余部分。此外,这为用户提供了一种将基础对象转换为派生对象的安全方式。我似乎缺少的是这样的代码是否是好的代码实践,或者是否有更简单/更好的方法来完成我想要做的事情?正如我之前提到的,我知道从独立类中的复制构造函数调用赋值运算符通常是不可行的,但是从另一个构造函数调用赋值运算符呢?

【问题讨论】:

嗯...为什么要避免在复制构造函数中使用赋值运算符? 见:***.com/questions/2639017/… 为什么不从派生类构造函数调用基类构造函数,而是通过赋值运算符? 看来Base 应该是成员而不是基地...... @BillyONEal,我当然明白你的意思。但是,鉴于 base 的实现,有一些封装问题需要解决。也就是说,base 中有一些函数是受保护的,需要在派生中使用,但用户不能真正访问它们,否则他们有机会真正对对象造成一些损害。长篇大论... 【参考方案1】:
Derived::Derived(const Base& base) 
  *this = base;

这默认构造Base 子对象在构造的Derived 对象中,然后分配它。你可能会做得更好:

Derived::Derived(const Base& base)
  : Base(base)


它使用Base的复制构造函数。

【讨论】:

是的,我一直在寻找一种在派生类中调用 base 的复制构造函数的方法,但在函数体中,我会被骂。忘记了初始化列表(我缺乏 C++ 语法技能又来了)!谢谢你的提示。另外,赋值运算符的实现有什么问题或不妥吗?我可以像现在一样调用基类的赋值运算符吗?再次感谢! @It'sPete 要回答有关您当前实现的问题,是的,您可以使用强制转换来触发继承的operator= 的调用。但是您必须强制转换为引用,而不是新对象,即使用static_cast&lt;Base&amp;&gt;(*this) = base;,而不是static_cast&lt;Base&gt;(*this) = base;。你现在的做法是创建一个新的临时对象并将base 的内容分配给它。 @jogojapan 谢谢你,这完全有道理......我最初来自 C 语言,现在仍然远离 C 风格的演员表。【参考方案2】:

在构造函数中你应该使用初始化列表:

Derived::Derived(const Base& base) : Base(base) 

如果你真的想在某个地方重新分配你的基本切片,你只需要显式调用已经存在的 op=:

*this = Base::operator=(base);

【讨论】:

@BalogPal *this = Base::operator=(base); 等价于this-&gt;operator=(this-&gt;Base::operator=(base));。所以是的,有两个任务。

以上是关于C++:在派生类构造函数中调用基类赋值运算符的错误形式?的主要内容,如果未能解决你的问题,请参考以下文章

如何从基类调用派生赋值运算符?

派生类在基类中删除时是不是会有隐式复制构造函数或赋值运算符?

继承默认构造函数,矛盾吗?

包含指向派生模板类的基类指针的类的赋值运算符和复制构造函数

C++继承

C++继承