2010-10-22 33 views
5

Có thể vượt qua đối tượng chưa được khởi tạo một lớp cha mẹ như trong ví dụ sauTham chiếu đến đối tượng chưa được khởi tạo iniside constructor

class C 
{ 
    public: 
     C(int i): 
      m_i(i) 
     {}; 

     int m_i; 
} 

class T 
{ 
    public: 
     T(C & c): 
      m_c(c) 
     { 
     }; 

     C & m_c; 
}; 


class ST : public T 
{ 
    public: 
     ST(): 
      T(m_ci), 
      m_ci(999) 
     { 
     }; 

     C m_ci; 
}; 

Trong class T constructor, c là một tham chiếu đến đối tượng chưa được khởi tạo. Nếu class T đang sử dụng đối tượng c trong khi xây dựng, điều này có thể dẫn đến lỗi. Nhưng kể từ khi nó không phải, điều này biên dịch và hoạt động tốt. Câu hỏi của tôi là - nó phanh một số loại mô hình hoặc chỉ thị thiết kế tốt? Nếu vậy, các lựa chọn thay thế là gì, bởi vì tôi thấy hữu ích khi phân bổ một đối tượng theo yêu cầu của cha mẹ trong một lớp con.

Trên một lưu ý phụ, tôi tự hỏi tại sao không thể thay đổi thứ tự khởi tạo, do đó trình tạo lớp cơ sở sẽ được gọi sau khi khởi tạo một số thành viên.

Trả lời

2

Bạn thể , nhưng bạn nhận được hành vi không xác định.

Trong các tiện ích của Boost, bạn sẽ tìm thấy base-from-member idiom được tạo bởi R. Samuel Klatchko. Về cơ bản, bạn tạo một cơ sở riêng tư ở vị trí của thành viên riêng tư. Căn cứ này được khởi tạo trước tiên và bạn có thể sử dụng nó cho các cơ sở khác:

// ... 

class C_base 
{ 
public: 
    C_base(int i) : 
    m_ci(i) 
    {} 

    C m_ci; 
}; 


class ST : 
    private C_base 
    public T 
{ 
    public: 
     ST() : 
      C_base(999), 
      T(m_ci), 
     { 
     }; 
}; 

Tiện ích của Boost loại bỏ mã lặp lại.

2

Tôi đã thấy điều này rất nhiều và nhiều trình biên dịch sẽ cảnh báo. Không sao nếu nhà xây dựng T không bao giờ đề cập đến tham chiếu c.

Nếu bạn không muốn cảnh báo, bạn cần thực hiện hai giai đoạn xây dựng. Thực hiện một bảo vệ Init(C&) phương pháp trong T, và sau đó gọi nó trong cơ thể ST constructor - may m_c sẽ cần phải là một con trỏ để làm điều đó (vì tài liệu tham khảo không thể được bố trí đối tượng khác)

2

Truyền tham chiếu hoặc con trỏ tới một thứ gì đó chưa được khởi tạo về mặt kỹ thuật là hoàn toàn OK. Nhưng lý do bạn hỏi có lẽ là bạn nghĩ rằng một cái gì đó dễ dàng có thể đi sai, rằng thông qua một số chuỗi các cuộc gọi, người ta có thể vô tình truy cập vào đối tượng trước khi nó được khởi tạo. Và tôi nghĩ đó là một mối quan tâm hợp lệ. Và có một điều mà có thể đi sai, cụ thể là mã mà trong lớp cơ sở T bây giờ có thể có thể làm mất hiệu lực bất biến lớp học của ST bằng cách thay đổi trực tiếp thành viên dữ liệu ST dụ ...

Vì vậy, tôi nghĩ rằng đó là một chút mạo hiểm.

Về thứ tự khởi tạo, C++ dựa trên ý tưởng xây dựng từ các phần lên, trong một cấu trúc phân cấp. Nếu một nhà xây dựng ném thì những thứ được xây dựng hoàn toàn sẽ bị phá hủy, tự động. Điều này sẽ khó khăn hơn hoặc kém hiệu quả hơn với thứ tự xây dựng tùy ý hơn.

Chúc mừng & hth.,

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