2012-03-28 39 views
62

Tôi không hiểu tại sao trong mã sau đây, khi tôi instanciate một đối tượng của loại daughter, các mặc định grandmother() constructor được gọi là?Tại sao hàm dựng mặc định được gọi là thừa kế ảo?

Tôi nghĩ rằng một trong những nhà xây dựng grandmother(int) nên được gọi (để làm theo các đặc điểm kỹ thuật của tôi xây dựng lớp mother lớp), hoặc mã này không nên biên dịch ở tất cả vì thừa kế ảo.

Trình biên dịch này âm thầm gọi grandmother hàm tạo mặc định ở lưng của tôi, trong khi tôi chưa bao giờ yêu cầu.

#include <iostream> 

class grandmother { 
public: 
    grandmother() { 
     std::cout << "grandmother (default)" << std::endl; 
    } 
    grandmother(int attr) { 
     std::cout << "grandmother: " << attr << std::endl; 
    } 
}; 

class mother: virtual public grandmother { 
public: 
    mother(int attr) : grandmother(attr) { 
     std::cout << "mother: " << attr << std::endl; 
    } 
}; 

class daughter: virtual public mother { 
public: 
    daughter(int attr) : mother(attr) { 
     std::cout << "daughter: " << attr << std::endl; 
    } 
}; 

int main() { 
    daughter x(0); 
} 
+0

Trình biên dịch (và phiên bản) nào? Với những đối số nào bạn đã biên dịch nó? – orlp

+0

gcc 4.6.3 20120306 (Mũ đỏ 4.6.3-2) trên fedora 15. Đối số là: -O0 -g3 -Wall -c -fmessage-length = 0 –

+0

g ++ 4.1.2 có cùng vấn đề: http: // codepad.org/L0jBXfSP – orlp

Trả lời

66

Khi sử dụng thừa kế ảo, hàm tạo của lớp cơ sở ảo được gọi trực tiếp bởi hàm tạo của lớp dẫn xuất nhất. Trong trường hợp này, hàm tạo daughter trực tiếp gọi hàm tạo grandmother.

Vì bạn không rõ ràng gọi số grandmother hàm tạo trong danh sách khởi tạo, hàm tạo mặc định sẽ được gọi. Để gọi các nhà xây dựng đúng, thay đổi nó để:

daugther(int attr) : grandmother(attr), mother(attr) { ... } 

Xem thêm This FAQ entry.

+2

Điều đó hoàn toàn có ý nghĩa, cảm ơn! Tất cả các nhà xây dựng trong hệ thống phân cấp được gọi từ lớp cuối cùng và không phải bởi lớp con tương ứng của họ. Không bao giờ nghĩ về điều đó. C++ spec đôi khi có thể phức tạp ... –

+0

Cảm ơn bạn! Vì vậy, trong trường hợp thừa kế ảo, cách tốt nhất để làm là gọi thủ công tất cả các hàm tạo của chuỗi. –

+0

Câu trả lời hay! Cám ơn! –

Các vấn đề liên quan