2013-04-30 34 views
10
  1. Các vấn đề cụ thể nào có thể tránh được với các hạn chế được quy định tại khoản này 12.7p3 (xem phần đầu của đoạn bên dưới)?Liên quan đến đoạn 12.7p3 trong tiêu chuẩn C++, tôi có các câu hỏi sau

  2. Trong ví dụ được hiển thị trong 12.7p3 (xem bên dưới) tại sao X(this) được xem là đã xác định? Có phải vì X không nằm trong đường dẫn E C D B A?

    struct A { }; 
    struct B : virtual A { }; 
    struct C : B { }; 
    struct D : virtual A { D(A*); }; 
    struct X { X(A*); }; 
    struct E : C, D, X { 
    E() : D(this), // undefined: upcast from E* to A* 
           // might use path E* - D* - A* 
           // but D is not constructed 
           // D((C*)this), // defined: 
           // E* - C* defined because E() has started 
           // and C* - A* defined because 
           // C fully constructed 
         X(this) { // defined: upon construction of X, 
           // C/B/D/A sublattice is fully constructed 
        } 
    }; 
    
  3. Hãy tìm thấy bên dưới bắt đầu đoạn 12.7p3:

Để rõ ràng hoặc ngầm chuyển đổi một con trỏ (một glvalue) đề cập đến một đối tượng của lớp X để một con trỏ (tham khảo) cho một cơ sở trực tiếp hoặc gián tiếp lớp B cơ sở X, việc xây dựng X và xây dựng tất cả của các căn cứ trực tiếp hoặc gián tiếp của nó trực tiếp hoặc gián tiếp lấy được từ B sẽ bắt đầu phá hủy các lớp này chưa hoàn thành, nếu không kết quả chuyển đổi sẽ không được xác định là hành vi không xác định.

Là nó đúng để nói rằng các thiết lập của tất cả các căn cứ trực tiếp và gián tiếp của X, nêu trên không bao gồm B, và vì điều này mã dưới đây được xác định rõ, dù thực tế là Base là một trực tiếp cơ sở của Derived và chưa bắt đầu?

struct Base{ Base(Base*); }; 

struct Derived : Base { 
    Derived() : Base(this) {}; 
}; 
+0

+1 chỉ dành cho nỗ lực hiếm khi cố gắng tìm câu trả lời trong tiêu chuẩn. – PlasmaHH

+0

@PlasmaHH một ví dụ điển hình về đạo đức làm việc lành mạnh theo kiểu cũ, tìm kiếm câu trả lời trong kinh thánh thay vì độc quyền với rất kinh nghiệm. – TemplateRex

Trả lời

6

những vấn đề cụ thể đang được tránh với những hạn chế áp đặt bởi 12.7p3 khoản này là gì (xem phần đầu của đoạn văn dưới đây)?

Các vấn đề phải làm với thực tế là, tại một số điểm, các con trỏ ảo (đến bảng ảo hoặc lớp cơ sở ảo) phải được khởi tạo cho lớp dẫn xuất. Đây là khởi tạo xảy ra trong "danh sách khởi tạo" (tức là, trước khi hàm khởi tạo) bắt đầu, thường ngay sau khi lớp cơ sở được xây dựng (ví dụ, sau khi lớp cơ sở B được xây dựng, con trỏ bảng ảo và con trỏ cơ sở ảo được đặt cho lớp X, và sau đó các thành viên dữ liệu được khởi tạo, và sau đó cơ thể của hàm tạo bắt đầu). Nói chung, thực hiện up-cast trước khi các con trỏ được khởi tạo sẽ mang lại hành vi không xác định, hoặc vì tra cứu con trỏ cần thiết không thể được thực hiện cho một cơ sở ảo hoặc con trỏ bảng ảo sẽ không được đặt chính xác cho các hàm ảo được gọi chính xác .

Trong ví dụ được hiển thị trong 12.7p3 (xem bên dưới) tại sao X (điều này) được coi là xác định? Có phải vì X không nằm trong đường dẫn E C D B A?

Vì trình tạo lớp cơ sở được gọi theo thứ tự xuất hiện trong khai báo lớp học (tức là, struct E : C, D, X {). Bởi vì các lớp cơ sở C và D đều được xây dựng, nên lớp cơ sở ảo chung A của chúng chắc chắn cũng được xây dựng. Và bởi vì X không được kế thừa từ lớp A, điều đó có nghĩa là có một đường dẫn được xây dựng hoàn chỉnh và rõ ràng khi thực hiện dàn diễn viên từ lớp E đến lớp A tại thời điểm này. Đó là lý do tại sao dòng đó được xác định rõ.

Là nó đúng để nói rằng các thiết lập của tất cả các căn cứ trực tiếp và gián tiếp của X, nêu trên không bao gồm B, và vì điều này mã dưới đây được xác định rõ, dù thực tế là Base là một trực tiếp cơ sở của Derived và chưa bắt đầu?

Tôi không chắc chắn tôi làm theo lời giải thích của bạn, nhưng tôi có thể cho bạn biết rằng mã bạn đã hiển thị không được xác định rõ. Khi gọi hàm tạo của Base bằng cách đúc Derived* this đến Base*, đối tượng lớp cơ sở trong lớp dẫn xuất chưa được tạo và do đó, diễn viên không xác định. Cách duy nhất để mã này có thể có ý nghĩa là nếu không có hàm ảo hoặc lớp cơ sở ảo nào liên quan đến cấu trúc phân cấp, trong trường hợp đó, mã đó sẽ không cần thiết vì con trỏ this đến lớp cơ sở đã được gửi đi. , hoàn toàn, với hàm tạo lớp cơ sở.

+1

+1, không chắc chắn nếu đáng chú ý, nhưng trong ví dụ từ tiêu chuẩn, nếu dòng 'D (this)' được viết lại là 'D (static_cast (this))' nó sẽ được xác định hoàn hảo. Vấn đề phát sinh chỉ khi trình biên dịch có thể quyết định sử dụng cơ sở 'D' để giải quyết vị trí của lớp con' A'. –

+0

Tôi không chắc chắn tôi đồng ý với kết luận của bạn về ví dụ 'Derived: Base' ở cuối. 'Base' không phải là một" cơ sở trực tiếp hoặc gián tiếp của 'Derived' trực tiếp hoặc gián tiếp có nguồn gốc từ' Base' ". (Điều kiện đầu tiên được đáp ứng, nó là một cơ sở của 'Derived', nhưng nó không bắt nguồn từ chính nó) –

+0

@Mikael Không đúng là bất kỳ cuộc gọi ảo nào bên trong một hàm tạo luôn trỏ đến hàm thành viên tương ứng với đối tượng dưới xây dựng? Nếu đây là trường hợp, tôi không hiểu tại sao điều khoản này lại quan trọng đến thế để tránh loại vấn đề mà bạn đã đề cập trong phần giải thích của bạn. – Alexander

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