2012-05-10 29 views
18
class A { 
     int i; 
public: 
     A() {cout<<"in A's def const\n";}; 
     A(int k) {cout<<"In A const\n"; i = k; } 
     }; 

class B : virtual public A { 
public: 
     B(){cout<<"in B's def const\n";}; 
     B(int i) : A(i) {cout<<"in B const\n";} 
     }; 

class C : public B { 
public: 
     C() {cout<<"in C def cstr\n";} 
     C(int i) : B(i) {cout<<"in C const\n";} 
     }; 

int main() 
{ 
     C c(2); 
     return 0; 
} 

Sản lượng trong trường hợp này làTrình tự gọi constructor trong thừa kế ảo

in A's def const 
in B const 
in C const 

Tại sao điều này không đi vào in A const

'Nó nên làm theo thứ tự của 1 arg gọi constructor. Nhưng những gì thực sự đang xảy ra trên bắt nguồn B từ A bằng cách sử dụng từ khóa ảo.

Có vài câu hỏi nữa

Thậm chí nếu tôi loại bỏ các từ khóa ảo trong chương trình ở trên và loại bỏ tất cả các nhà xây dựng mặc định nó mang lại cho lỗi. Vì vậy, tại sao nó cần các nhà xây dựng def

Trả lời

13

Các nhà xây dựng cho các lớp cơ sở ảo luôn được gọi từ lớp dẫn xuất nhất, sử dụng bất kỳ đối số nào nó có thể vượt qua. Trong trường hợp của bạn, lớp được sinh ra nhiều nhất không chỉ định khởi tạo cho A, do đó hàm tạo mặc định được sử dụng.

+1

@james .... bạn muốn nói rằng lớp dẫn xuất nhất ở đây nghĩa là C nên chỉ định trình khởi tạo cho A. Nhưng, khi xóa một hàm tạo mặc định và thêm C (int i): A (i), B (i) trong C của constructor nó không làm việc – Kunal

+0

@MikeDeSimone ... ya tôi đã viết cùng nhưng loại bỏ constructor mặc định của A nhưng tôi nhận được lỗi biên dịch ... bạn có thể vui lòng giải thích tại sao điều này là như vậy ... và làm thế nào để chăm sóc nếu tôi có một thừa kế phức tạp liên quan đến. – Kunal

+0

@Kunal: Vâng, tôi đã xóa nhận xét của tôi vì bạn thực sự đã thử nó. Vì vậy, ở đây chúng tôi có một câu trả lời, bỏ phiếu, không hoạt động. @ James, vui lòng giải thích cách sửa mã để hàm tạo 'A (int)' được gọi. –

5

JamesKanze has explained, trong trường hợp thừa kế virtual đó là lớp được thừa hưởng nhất gọi là hàm tạo lớp cơ sở ảo. Vì vậy, nếu bạn muốn hàm tạo của A lấy số nguyên được gọi, bạn cần thêm số đó vào danh sách khởi tạo C.

C(int i) : A(i), B(i) {cout<<"in C const\n";} 

Đối với phần thứ hai của câu hỏi của bạn, nhà thầu mặc định không bắt buộc, nhưng sau đó các lớp được thừa kế phải gọi các nhà xây dựng không phải mặc định một cách rõ ràng, kể từ khi biên dịch không thể làm điều đó cho bạn trong sự vắng mặt của một constructor không mặc định.

#include <iostream> 
using namespace std; 

class A { 
    int i; 
public: 
    // A() {cout<<"in A's def const\n";}; 
    A(int k) {cout<<"In A const\n"; i = k; } 
}; 

class B : virtual public A { 
public: 
    // B(){cout<<"in B's def const\n";}; 
    B(int i) : A(i) {cout<<"in B const\n";} 
}; 

class C : public B { 
public: 
    C() : A(42), B(42) {cout<<"in C def cstr\n";} 
    C(int i) : A(i), B(i) {cout<<"in C const\n";} 
}; 

int main() 
{ 
    C c(2), c2; 
    return 0; 
} 

này in ra

In A const 
in B const 
in C const 
In A const 
in B const 
in C def cstr 
+0

@praetorian ... cảm ơn câu trả lời của bạn. Nhưng tôi vẫn chưa rõ một điều ... tại sao cần phải cung cấp cho C(): A (42), B (42) ở đó? Vui lòng làm rõ – Kunal

+2

@Kunal Mỗi hàm tạo lớp dẫn xuất (đối với các kiểu không phải POD) phải khởi tạo hàm tạo lớp cơ sở của nó. Khi bạn không liệt kê rõ ràng hàm tạo cơ sở, trình biên dịch sẽ gọi hàm dựng mặc định cho bạn. Nếu không có hàm tạo cơ sở mặc định như vậy tồn tại, bạn phải gọi một hàm tạo cơ sở hiện có một cách rõ ràng. – Praetorian

+0

có nghĩa là A() sẽ được gọi hai lần? những gì xảy ra với các cuộc gọi đến A() bên trong B()? – Youda008

2

Có hai câu hỏi ở đây.

Tại sao điều này không tham gia vào A const?

Vì bạn đang sử dụng thừa kế ảo.

Khi bạn sử dụng thừa kế ảo, Initialization list of most-derived-class's ctor directly invokes the virtual base class's ctor.. Trong trường hợp này, điều đó có nghĩa là hàm tạo của C gọi hàm tạo của A trực tiếp trực tiếp. Vì bạn chưa chỉ định hàm tạo nào của A để gọi trong danh sách khởi tạo C, hàm tạo mặc định được gọi.

này được cố định bằng cách thay đổi thực hiện của bạn của C::C(int) tới:

C(int i) : A(i), B(i) {cout<<"in C const\n";} 

Nếu tôi loại bỏ các từ khóa ảo trong chương trình ở trên và loại bỏ tất cả các nhà xây dựng mặc định nó mang lại cho lỗi. Vì vậy, tại sao nó cần def defector ?

B cũng không chỉ định hàm nào là A để gọi, do đó hàm tạo mặc định được sử dụng.Nếu bạn xóa A s def ctor, B không thể được biên dịch.

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