2010-02-18 40 views
111

Có thể sử dụng danh sách khởi tạo của hàm tạo lớp con để khởi tạo các thành viên dữ liệu được khai báo là được bảo vệ trong lớp cha không? Tôi không thể có được nó để làm việc. Tôi có thể làm việc xung quanh nó, nhưng sẽ tốt hơn nếu tôi không phải làm vậy.Khởi tạo các thành viên được bảo vệ của phụ huynh với danh sách khởi tạo (C++)

Một số mẫu mã:

class Parent 
{ 
protected: 
    std::string something; 
}; 

class Child : public Parent 
{ 
private: 
    Child() : something("Hello, World!") 
    { 
    } 
}; 

Khi tôi cố gắng này, trình biên dịch nói với tôi: "class 'trẻ em' không có bất kỳ lĩnh vực có tên là 'cái gì đó'". Có phải bất cư thứ gì như thế này đều được? Nếu vậy, cú pháp là gì?

Rất cám ơn!

Trả lời

103

Không thể theo cách bạn mô tả. Bạn sẽ phải thêm một hàm tạo (có thể được bảo vệ) vào lớp cơ sở để chuyển tiếp nó cùng. Một cái gì đó như:

class Parent 
{ 
protected: 
    Parent(const std::string& something) : something(something) 
    {} 

    std::string something; 
} 

class Child : public Parent 
{ 
private: 
    Child() : Parent("Hello, World!") 
    { 
    } 
} 
+2

Đây chính là cách giải quyết Tôi đã muốn đưa ra. Ít nhất bây giờ tôi không phải lo lắng về việc liệu nó có thể được thực hiện hay không. :) – Stephen

11

Bạn không có thể khởi tạo các thành viên của tầng lớp phụ huynh trong lớp có nguồn gốc danh sách constructor khởi tạo. Cho dù chúng được bảo vệ, công khai hay gì khác cũng không quan trọng.

Trong ví dụ của bạn, thành viên something là thành viên của lớp Parent, có nghĩa là nó chỉ có thể được khởi tạo trong danh sách khởi tạo hàm dựng Parent lớp.

51

Khi trình biên dịch đi qua danh sách bộ khởi tạo, đối tượng lớp dẫn xuất chưa được tạo thành. Các nhà xây dựng lớp cơ sở đã không được gọi cho đến lúc đó. Chỉ sau khi hàm tạo lớp cơ sở được gọi là, something hiện hữu. Do đó vấn đề. Khi bạn không gọi hàm tạo của lớp cơ sở một cách rõ ràng, trình biên dịch thực hiện điều đó cho bạn (bằng cách tạo ra hàm tạo tầm thường thích hợp cho lớp cơ sở). Điều này làm cho thành viên something được khởi chạy mặc định.

Từ C++ 0x dự thảo:

12.6.2 Khởi tạo các căn cứ và các thành viên

Names trong một mem-initializer-id được nhìn lên trong phạm vi của lớp của nhà xây dựng và, nếu không tìm thấy trong phạm vi đó, được tra cứu trong phạm vi có chứa định nghĩa của hàm tạo. [Lưu ý: nếu lớp học của nhà xây dựng chứa thành viên có cùng tên với một lớp cơ sở ảo hoặc lớp cơ sở ảo của lớp học, mem-initializer-id đặt tên cho thành viên hoặc lớp cơ sở và bao gồm một tham chiếu cho thành viên lớp học. Id meminitializer- cho lớp cơ sở ẩn có thể được chỉ định bằng cách sử dụng tên có tiêu chuẩn . —end note] Trừ khi tên mem-initializer-id là lớp của nhà xây dựng, một dữ liệu không tĩnh thành viên của lớp khởi tạo hoặc cơ sở trực tiếp hoặc ảo của lớp đó, trình khởi tạo mem bị hỏng .

Lưu ý: Mỏ nhấn mạnh.

+2

Cảm ơn bạn đã chỉ cho tôi "lý do". Làm cho toàn bộ ý nghĩa. Tôi đã đi từ C + + quá lâu ... :) – Stephen

0

lẽ bạn có thể thử nó theo cách đó bằng cách sử dụng từ khóa "sử dụng"

class Parent 
{ 

protected: 
std::string something; 
}; 

class Child : public Parent 
{ 

private: 
using Parent::something; 
Child() 
{ 
    something="Hello, World!"; 
} 
}; 
Các vấn đề liên quan