2010-11-17 42 views
10

Tôi bỏ về vấn đề này ...dynamic_cast nhầm lẫn

$ 5.2.7/2- "Nếu T là một kiểu con trỏ, v sẽ là một rvalue của một con trỏ đến hoàn chỉnh kiểu lớp, và kết quả là giá trị của loại T. Nếu T là loại tham chiếu , v sẽ là một giá trị của loại lớp hoàn chỉnh và kết quả là là một loại giá trị của loại được T. "

Theo như trên, mã sau phải được định dạng đúng.

struct A{}; 
struct B : A{}; 

int main(){ 
    B b; 
    A a, &ar1 = b; 

    B& rb1 = dynamic_cast<B&>(ar1); // Does not $5.2.7/2 apply here? 
    B& rb2 = dynamic_cast<B&>(a); // and also here? 
} 

Nhưng không phải. Tất cả các trình biên dịch phàn nàn về các toán hạng để dynamic_cast không phải là đa hình phù hợp với

$ 5.2.7/6- Nếu không, v sẽ là một con trỏ hoặc một vế trái của một kiểu đa hình (10,3).

Vì vậy, câu hỏi của tôi là $ 5.2.7/2 có nghĩa là gì? Tại sao $ 5.2.7/6 đá ở đây?

Trả lời

3

"Nếu không" trong trường hợp này có nghĩa là "trừ khi các điều kiện trong 5.2.7/5 được áp dụng".

Bạn có thể nói điều này bởi vì/2 đặt một yêu cầu về chương trình liên quan đến toán hạng của dynamic_cast (lưu ý ngôn ngữ "phải" của "v sẽ là một lvalue" so với "là" ngôn ngữ của "kết quả là một lvalue "). Nói chung với các địa điểm khác trong tiêu chuẩn, việc thể hiện yêu cầu không nhất thiết có nghĩa là yêu cầu chỉ yêu cầu. Các điều khoản khác có thể nêu thêm các yêu cầu. Trong trường hợp này,/6 nêu rõ yêu cầu bổ sung chỉ áp dụng trong một số trường hợp nhất định, tùy thuộc vào T và loại tĩnh của v.

/3,/4,/5 đang cho bạn biết về giá trị của kết quả và chúng hoàn toàn phù hợp với yêu cầu trong/2. Không ai trong số họ bắt đầu với "Nếu không". Vì vậy, với tôi nó khá rõ ràng rằng họ không tạo thành một chuỗi "khác nếu" bắt đầu từ/2.

Một số dấu ngoặc hoặc thứ gì đó có thể làm rõ hơn (tức là "khác" trong/6 áp dụng cho "nếu" trong/5, chứ không phải là "if" trong/2,/3 hoặc/4) . Nhưng đó không chỉ là kiểu nhà.

Ngoài bất cứ điều gì khác, "nếu không" trong/5 một cách hợp lý không thể áp dụng có ý nghĩa với các điều kiện trong/2./1 nói rằng T phải là "con trỏ hoặc tham chiếu đến loại lớp hoàn chỉnh hoặc cvvoid*"./2 bao gồm hai trường hợp - loại con trỏ và loại tham chiếu. Đó là tất cả mọi thứ. Không có "khác" tới/2 (trừ khi nó được nói "nếu không, trình biên dịch phù hợp phải đưa ra chẩn đoán", nhưng điều đó ngầm)

+0

là có bất kỳ trường hợp nào khác mà 'nếu không' trong tiêu chuẩn được sử dụng trong một * khả năng * không rõ ràng cách – Chubsdad

+0

@ Chubsdad: Tôi mong đợi như vậy. –

+0

sự khác biệt b/w 'sẽ' và 'sẽ' như được sử dụng trong tiêu chuẩn là gì? – Chubsdad

9

Vâng, tất cả các yêu cầu trong 5.2.7 phải được quan sát cùng nhau. Bạn không thể chỉ dừng lại sau 5.2.7/2 và bắt đầu viết mã được cho là thỏa mãn mọi thứ "lên đến 5.2.7/2". Toàn bộ 5.2.7 xác định đặc điểm kỹ thuật của dynamic_cast.

Yêu cầu đa hình được tách ra vì nó là có điều kiện. Khi bạn sử dụng dynamic_cast để tải lên, yêu cầu đa hình không áp dụng (trên thực tế, dynamic_cast tương đương với static_cast khi phát sóng). Yêu cầu đa hình chỉ áp dụng khi bạn sử dụng dynamic_cast để xóa hoặc truyền phát.

Đặc điểm kỹ thuật của dynamic_cast được tổ chức theo tuần tự, có nghĩa là nó sẽ xử lý các trường hợp đơn giản trước, sau đó tiếp tục đến các ứng dụng phức tạp hơn. Bạn có nghĩa vụ phải đọc nó từng bước, cho đến khi nó bao gồm tình hình cụ thể của bạn. Mọi thứ bạn đọc dọc theo đường dẫn đó sẽ áp dụng tổng hợp, Và "nếu không" có nghĩa là: "nếu chúng tôi chưa đề cập đến trường hợp của bạn, hãy tiếp tục đọc".

+2

Mmmm. Đuợc. Nhưng "nghĩa khác" nghĩa là gì? – sharptooth

+0

chính xác câu hỏi của tôi. Người dùng 'khác' trong nhiều phần khác của tiêu chuẩn cho phép loại thuật toán 'bước khôn ngoan' tiến hành. – Chubsdad

+0

Cảm ơn AndreyT. Tôi nghĩ Steve đặt nó theo cách thuyết phục. 'Nếu không' áp dụng cho 5.2.7/5 thay vì tất cả các điều khoản trước đó. Tôi hy vọng những nhầm lẫn như vậy có một cách để đạt được các tiêu chuẩn committe cho địa chỉ tiềm năng. – Chubsdad

4

Để thực hiện downcast như trong ví dụ của bạn, Struct A cần phải được đa hình và có RTTI. Dưới đây là phiên bản được điều chỉnh hoạt động, đến một điểm:

struct A{virtual void f(){}}; 
struct B : A{}; 

int main(){ 
    B b; 
    A a, &ar1 = b; 

    B& rb1 = dynamic_cast<B&>(ar1); // Does not $5.2.7/2 apply here? 
    //B& rb2 = dynamic_cast<B&>(a); // and also here? 
} 

Bằng cách thêm ảo làm cho nó đa hình, RTTI được bật cho lớp, cho phép làm chậm.

Lưu ý rằng ví dụ thứ hai của bạn không thể hoạt động - vì bạn đang truyền một nhóm (a) thành tham chiếu đến nhóm - không được phép.


Cập nhật:

Mã của bạn không được phép theo 5.2.7.5 và không phải là phép theo 5.2.7.6. Điều chỉnh của tôi làm cho nó hoạt động dưới 5.2.7.6

+0

Cảm ơn Alex. Tuy nhiên đó không phải là câu hỏi của tôi. – Chubsdad