2012-02-06 117 views
14

有这样的代码:赋值运算符继承

#include <iostream> 

class Base { 
public: 
    Base(){ 
     std::cout << "Constructor base" << std::endl; 
    } 
    ~Base(){ 
     std::cout << "Destructor base" << std::endl; 
    } 
    Base& operator=(const Base& a){ 
     std::cout << "Assignment base" << std::endl; 
    } 
}; 

class Derived : public Base{ 
public: 

}; 

int main (int argc, char **argv) { 
    Derived p; 
    Derived p2; 
    p2 = p; 
    return 0; 
} 

编译后的输出用g ++ 4.6:

Constructor base 
Constructor base 
Assignment base 
Destructor base 
Destructor base 

为什么基类的赋值运算符称为altough据说赋值运算符不遗传?

+1

[C++中运算符的继承问题]可能的重复(http://stackoverflow.com/questions/3882186/trouble-with-inheritance-of-operator-in-c) – 2012-02-06 14:29:49

回答

13

您没有默认

Derived& operator=(const Base& a); 

Derived类。

默认的赋值运算符,但是,创建:

Derived& operator=(const Derived& a); 

,这从Base调用赋值运算符。所以这不是继承赋值运算符的问题,而是通过派生类中的默认生成运算符调用它。

+9

运营商=从基础类继承,因为我引用了98 C++标准“运营商功能是以与其他基类功能相同的方式继承。“它刚被隐式创建的operator = for Derived类隐藏。 – Gob00st 2012-02-06 15:12:17

+1

“它刚被隐式创建的运算符= Derived类隐藏”。就像基类有void func(int)并且派生类有void func(double)一样,基类函数void func(int)是隐藏的。在类似的行上,基类operator =被派生类operator =隐藏。 – Sandeep 2015-04-19 23:07:44

+0

...并且要清楚,因为基础'operator ='只被隐藏,所以它可以在派生类中用'Base :: operator =;'和'boom:'来隐藏,它继承了它。请参阅:http://stackoverflow.com/questions/4122214/why-operator-doesnt-get-inherited-from-a-template-class – 2016-09-08 22:01:35

-1

这是因为创建的默认赋值运算符调用它的基本赋值运算符,即它不是继承的,但仍被称为默认赋值运算符的一部分。

+0

赋值运算符**是**从基地继承。它只是由编译器生成的派生类隐藏。使用'使用Base :: operator =;'可以通过取消隐藏基本实现并通过派生类使其可用来证明这一点。请参阅:http://stackoverflow.com/questions/4122214/why-operator-doesnt-get-inherited-from-a-template-class – 2016-09-08 21:58:39

31

实际上,所谓的是Derived的隐式定义operator =。编译器提供的定义依次调用​​operator =作为Base,您会看到相应的输出。构造函数和析构函数也是一样。当你把它交给编译器来定义operator =,它定义它,如下所示:

Derived& operator = (const Derived& rhs) 
{ 
    Base1::operator =(rhs); 
    ... 
    Basen::operator =(rhs); 
    member1 = rhs.member1; 
    ... 
    membern = rhs.membern; 
} 

其中Base1,...,Basen是类的基础(在继承列表中指定它们的顺序)和member1, ..., membern是派生成员(不包括被继承的成员)按您在类定义中声明的顺序排列。

-1

赋值运算符确实不被继承。继承该运算符将使您能够将Base分配给Derived,但Base b; p = a;将(正确)无法编译。

会发生什么情况是编译器生成operator=,因为您尚未为Derived定义一个自定义的。自动生成的operator=将调用所有基类和所有成员的赋值操作符。在这方面,它与构造函数/析构函数非常相似,它们也在所有基类/成员上调用相应的函数。

+1

赋值运算符**从基础继承。它只是由编译器生成的派生类隐藏。使用'使用Base :: operator =;'可以通过取消隐藏基本实现并通过派生类使其可用来证明这一点。请参阅:http://stackoverflow.com/questions/4122214/why-operator-doesnt-get-inherited-from-a-template-class – 2016-09-08 21:58:12

7

标准说(12.8):

赋值运算符应以非静态成员函数 正好有一个参数来实现。因为拷贝赋值 如果用户(12.8)未声明 ,则隐式声明运算符operator = =,但派生类的拷贝赋值运算符总是隐藏基类赋值运算符 。衍生

然后赋值运算符调用你的基地

的非工会 类X的隐式定义的复制/移动赋值运算符执行按成员禁止复制/移动其子对象的分配。 首先指定X的直接基类,按其在基指定符列表中的 声明的顺序,然后按照它们的 声明的顺序分配X的非静态数据成员的即时 在类定义中。

17

您还可以使用 “使用”:

class Derived : public Base{ 
public: 
    using Base::operator=; 
}; 

http://en.cppreference.com/w/cpp/language/using_declaration

我看到这篇文章的几个时间之前有人帮助我与此有关。

+2

最后,有人说。 +1。另见:http://stackoverflow.com/questions/4122214/why-operator-doesnt-get-inherited-from-a-template-class – 2016-09-08 21:59:06