不会自动继承的函数

Posted

技术标签:

【中文标题】不会自动继承的函数【英文标题】:Functions that do not automatically inherit 【发布时间】:2013-06-06 08:59:06 【问题描述】:

在 c++ 中,我在 bruce eckel 中读到,是:

    构造函数 析构函数 Operator =(因为它像构造函数那样做)

但这段代码说明了其他内容

#include<iostream>             
using namespace std;`                   

class A 
 public:
   A & operator= (A &a) 
    cout<<" base class assignment operator called ";
    return *this;
   
;

class B: public A  ;

int main()

  B a, b;
  a.A::operator=(b); //calling base class assignment operator function
                // using derived class
  a = b; // this also works
  //getchar();
  return 0;

   

输出:调用基类赋值运算符

请解释一下。

【问题讨论】:

您正在显式调用该函数。为什么会有惊喜? 他很惊讶这两个作业都调用了 A::operator=() 我猜。但是由于A是每个B的一部分,B的隐式赋值会调用子对象A的赋值。 @akash 程序应该输出base class assignment operator called base class assignment operator called @akash 如果您的问题已被回答,请考虑标记正确答案。 【参考方案1】:

其实说operator =不被继承是不对的。问题是它被派生类隐式生成的operator =隐藏,因此(例如)下面代码中的赋值是非法的: p>

A a;
B b;
b = a;

由于B 类没有任何operator = 接受A,而只有一个隐式生成的具有以下签名的复制赋值运算符:

B& operator = (B const&)

这种情况与派生类中的普通成员函数在基类中隐藏同名成员函数的情况没有什么不同。

对于常规成员函数,你可以在你的类中有一个 using 声明,使基类的 operator = 可用:

class B: public A

public:
    using A::operator =;
//  ^^^^^^^^^^^^^^^^^^^^
;

这将使前面示例中的分配编译。

【讨论】:

但是如果我不使用它,那么简单地写 a = b 呢?如何调用基类版本?见 o/p @akash: abB 类型的对象。正如我在回答中解释的那样,B 有一个隐式生成的operator =,因此表达式a = b 是有效的。但是隐式生成的运算符 hide 来自基类的运算符,因此,如果您想通过依赖该赋值运算符将 A 类型的对象分配给 B 类型的对象,你会有麻烦。我认为我的回答说明了这一点 @AndyProwl 我认为 op 只是没有意识到 B 的隐式赋值运算符将为其 A 类型的子对象调用 A 的赋值运算符。 【参考方案2】:

根据http://www.linuxtopia.org/online_books/programming_books/thinking_in_c++/Chapter14_010.html,当您没有为您的类定义构造函数、析构函数或= 运算符时,它会自动创建所有这三个的简单版本。

“代替继承,如果您不自己创建这些函数,则由编译器合成它们。(使用构造函数,您不能创建任何构造函数以使编译器合成默认构造函数和复制-构造函数。)合成的构造函数使用成员初始化,合成的 operator= 使用成员赋值。”

因此,B 有一个由编译器自动生成的综合= 运算符。

【讨论】:

【参考方案3】:

A 的 operator=() 没有继承。相反,基赋值运算符是从派生类赋值运算符中调用的,因为隐式赋值运算符“简单地”分配所有成员和基类。

(请参阅标准 [Draft N3242] §12.8 了解有关何时隐式生成默认复制或移动分配以及以何种形式生成的信息。)

标准(草案 N3242)说:

§12.8 / 29

非联合类 X 的隐式定义的复制/移动赋值运算符执行其子对象的成员复制/移动赋值。 首先分配 X 的直接基类,按照它们在 base-specifier-list 中的声明顺序,然后分配 X 的直接非静态数据成员,按照顺序它们是在类定义中声明的。

在那里我们得到了赋值运算符。

XBdirect base classA。所以在B的隐式赋值运算符中,它的A类型的子对象将使用A::operator=(...)进行赋值。

注意:最好通过 const 引用(如果使用复制和交换,则按值)提供赋值运算符参数。

【讨论】:

以上是关于不会自动继承的函数的主要内容,如果未能解决你的问题,请参考以下文章

java继承当中都有一些什么样的构造函数规则?

JAVA继承中的构造函数

python特性小记

为啥具有相同名称但不同签名的多个继承函数不会被视为重载函数?

python-子类构造函数调用super().__init__()

[C++11 类的改进] --- 继承控制:=default和=delete