2012-02-06 29 views
14

Có mã này:Chuyển nhượng nhà điều hành thừa kế

#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; 
} 

Kết quả sau khi biên dịch bằng g ++ 4.6:

Constructor base 
Constructor base 
Assignment base 
Destructor base 
Destructor base 

Tại sao nhiệm vụ điều hành của lớp cơ sở được gọi là altough người ta nói rằng toán tử gán không phải là thừa hưởng?

+1

có thể trùng lặp của [Trouble with inheritance of operator = in C++] (http://stackoverflow.com/questions/3882186/trouble-with-inheritance-of-operator-in-c) –

Trả lời

13

Bạn không có mặc định

Derived& operator=(const Base& a); 

trong lớp Derived của bạn.

Một toán tử gán mặc định, tuy nhiên, được tạo ra:

Derived& operator=(const Derived& a); 

và điều này gọi là toán tử gán từ Base. Vì vậy, nó không phải là vấn đề kế thừa toán tử gán, nhưng gọi nó thông qua toán tử được tạo mặc định trong lớp dẫn xuất của bạn.

+9

operator = được kế thừa từ lớp dựa trên như tôi trích dẫn từ tiêu chuẩn 98 C++ "Các hàm toán tử là được kế thừa giống như các hàm lớp cơ sở khác. " Nó vừa bị ẩn bởi toán tử ngầm được tạo ra = cho lớp Derived. – Gob00st

+1

"Nó vừa bị ẩn bởi toán tử ngầm được tạo ra = cho lớp Derived". Cũng giống như nếu lớp cơ sở có void func (int) và lớp dẫn xuất có void func (double), hàm lớp cơ sở void func (int) bị ẩn. Trên các dòng tương tự, toán tử lớp cơ sở = được ẩn bởi toán tử lớp dẫn xuất =. – Sandeep

+0

... và phải rõ ràng, vì toán tử 'operator =' cơ sở chỉ bị ẩn, nó có thể được ẩn trong lớp dẫn xuất với 'using Base :: operator =;' và boom: có nó, được kế thừa. Xem: http://stackoverflow.com/questions/4122214/why-operator-doesnt-get-inherited-from-a-template-class –

-1

Đó là do toán tử gán mặc định đã tạo cuộc gọi là toán tử gán cơ sở, nghĩa là toán tử không được kế thừa nhưng vẫn được gọi là một phần của toán tử gán mặc định.

+0

Toán tử gán ** là ** được thừa hưởng từ cơ sở. Nó chỉ bị ẩn bởi trình biên dịch được tạo ra trong lớp dẫn xuất. Sử dụng 'using Base :: operator =;' sẽ chứng minh điều này bằng cách bỏ ẩn việc triển khai cơ sở và làm cho nó có sẵn thông qua lớp dẫn xuất. Xem: http://stackoverflow.com/questions/4122214/why-operator-doesnt-get-inherited-from-a-template-class –

31

Thực ra, những gì được gọi là được xác định rõ ràng operator = cho Derived. Định nghĩa được cung cấp bởi trình biên dịch lần lượt gọi operator = cho Base và bạn thấy đầu ra tương ứng. Điều tương tự là với constructor và destructor. Khi bạn rời khỏi nó để trình biên dịch để xác định operator =, nó định nghĩa nó như sau:

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

nơi Base1,...,Basen là cơ sở của lớp (theo thứ tự xác định chúng trong danh sách thừa kế) và member1, ..., membern là những thành viên của nguồn gốc (không tính các thành viên đã được kế thừa) theo thứ tự bạn khai báo chúng trong định nghĩa lớp.

-1

Nhà điều hành chuyển nhượng thực sự không được kế thừa. Thừa kế toán tử đó sẽ cho phép bạn chỉ định một Base cho một số Derived, tuy nhiên Base b; p = a; sẽ (đúng) không biên dịch được.

Điều gì xảy ra là trình biên dịch tạo ra một operator=, vì bạn chưa xác định một tùy chỉnh cho Derived. Tự động phát hiện operator= sẽ gọi các toán tử gán của tất cả các lớp cơ sở và tất cả các thành viên. Trong khía cạnh đó, nó giống với constructor/destructors, cũng gọi hàm tương ứng trên tất cả các Base/members.

+1

Toán tử gán ** được ** kế thừa từ cơ số. Nó chỉ bị ẩn bởi trình biên dịch được tạo ra trong lớp dẫn xuất. Sử dụng 'using Base :: operator =;' sẽ chứng minh điều này bằng cách bỏ ẩn việc triển khai cơ sở và làm cho nó có sẵn thông qua lớp dẫn xuất. Xem: http://stackoverflow.com/questions/4122214/why-operator-doesnt-get-inherited-from-a-template-class –

7

Chuẩn nói (12,8):

Một toán tử gán được thực hiện bởi một tổ chức phi tĩnh thành viên chức năng với chính xác một tham số. Bởi vì việc gán bản sao toán tử operator = được khai báo hoàn toàn cho một lớp nếu không được khai báo là bởi người dùng (12.8), toán tử gán lớp cơ sở luôn bị ẩn bởi toán tử gán bản sao của lớp dẫn xuất.

và sau đó phân công điều hành của nguồn gốc gọi cơ sở của bạn

Các ngầm định nghĩa toán tử gán sao chép/di chuyển cho một tổ chức phi đoàn lớp X thực hiện memberwise copy-/di chuyển nhượng subobjects của nó. Các lớp cơ sở trực tiếp của X được chỉ định trước, theo thứ tự của khai báo trong danh sách-specifier-list, và sau đó là thành viên dữ liệu không tĩnh của X được chỉ định, theo thứ tự mà chúng được khai báo là trong định nghĩa lớp.

17

Bạn cũng có thể sử dụng "sử dụng":

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

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

Tôi đọc bài nhiều thời gian trước khi ai đó giúp tôi với điều này.

+2

Cuối cùng, ai đó đã nói điều đó. +1. Xem thêm: http://stackoverflow.com/questions/4122214/why-operator-doesnt-get-inherited-from-a-template-class –