2010-01-17 13 views
12

Tôi có một cái gì đó tương tự như sau trong mã của tôi:bảng ảo trên lớp nặc danh

#include <iostream> 
#include <cstdlib> 

struct Base 
{ 
    virtual int Virtual() = 0; 
}; 

struct Child 
{ 
    struct : public Base 
    { 
    virtual int Virtual() { return 1; } 
    } First; 

    struct : public Base 
    { 
    virtual int Virtual() { return 2; } 
    } Second; 
}; 

int main() 
{ 
    Child child; 
    printf("ble: %i\n", ((Base*)&child.First)->Virtual()); 
    printf("ble: %i\n", ((Base*)&child.Second)->Virtual()); 

    system("PAUSE"); 
    return 0; 
} 

tôi mong đợi này để cung cấp sản lượng này:

ble: 1 
ble: 2 

và nó làm như vậy, khi biên soạn dưới GCC (3.4.5 Tôi tin).

Biên dịch và chạy này dưới Visual Studio 2008 tuy nhiên, mang đến cho này:

ble: 2 
ble: 2 

là gì thú vị, là nếu tôi cung cấp cho các tên struct cơ sở có nguồn gốc từ (struct s1 : public Base), nó hoạt động một cách chính xác.

Hành vi nào, nếu có, là chính xác? VS có bị prissy hay là nó tuân theo tiêu chuẩn? Tôi có thiếu cái gì quan trọng ở đây không?

+1

Làm việc như mong đợi trong gcc.Mặc dù là thẳng thắn Tôi đã hy vọng nó không được biên dịch. –

+2

* VS tôn trọng tiêu chuẩn *? Ha ha ha ha ha ... – wallyk

+3

Hey, VC++ đã nhận được tốt hơn nhiều ở đó. – GManNickG

Trả lời

2

Có thể nhìn thấy cách MSVC nhận được sai từ các biểu tượng gỡ lỗi. Nó tạo ra các tên tạm thời cho các cấu trúc ẩn danh, tương ứng Child::<unnamed-type-First>Child::<unnamed-type-Second>. Tuy nhiên chỉ có một vtable, nó được đặt tên là Child::<unnamed-tag>::'vftable' và cả hai nhà xây dựng đều sử dụng nó. Tên khác cho vtable chắc chắn là một phần của lỗi.

Có một số lỗi được báo cáo tại connection.microsoft.com có ​​liên quan đến các loại ẩn danh, không có lỗi nào trong số đó từng làm cho trạng thái "phải sửa lỗi". Không phải là người bạn tìm thấy mặc dù, afaict. Có lẽ cách giải quyết quá đơn giản.

7

Dường như đây là lỗi trong VS 2008, có thể do nó ghi đè hoặc bỏ qua vtable cho lớp chưa đặt tên đầu tiên có lợi cho vtable cho thứ hai vì tên nội bộ giống hệt nhau. (Khi bạn đặt tên một cách rõ ràng, tên nội bộ của vtables không còn giống hệt nhau nữa.)

Theo như tiêu chuẩn, điều này sẽ hoạt động như bạn mong đợi và gcc là đúng.

+0

(+1) giải thích bằng văn bản. –

1

Tôi có thể xác nhận đây là lỗi đã biết trong trình biên dịch VC (và nó repos trong VC10); hai lớp ẩn danh đang chia sẻ không chính xác một vtable.

Cấu trúc ẩn danh là không một phần của tiêu chuẩn C++.

Chỉnh sửa: Cấu trúc ẩn danh là loại thuật ngữ không rõ ràng. Nó có thể có nghĩa là hai điều:

class outer 
{ 
public: 
    struct { 
     int a; 
     int b; 
    } m_a; // 1 

    struct { 
     int c; 
    };  // 2 

    union { 
     int d; 
     int e; 
    };  // 3 
}; 

1 là những gì đang diễn ra ở đây, tên tốt hơn cấu trúc ẩn danh sẽ là "cấu trúc chưa đặt tên". Bản thân kiểu cấu trúc không có tên, nhưng đối tượng đó thực hiện (m_a).

2 còn được gọi là cấu trúc ẩn danh và không phải là C++ hợp pháp. Không có tên đối tượng, và ý tưởng là bạn có thể truy cập trực tiếp vào trường 'c' trên các đối tượng kiểu bên ngoài. Điều này biên dịch chỉ vì một phần mở rộng trình biên dịch trong Visual Studio (sẽ thất bại dưới/Za)

3 Công đoàn ẩn danh, ngược lại, là hợp pháp C++.

Tôi nhầm lẫn cả hai, bởi vì ở đây chúng tôi gọi số 1 là "cấu trúc ẩn danh" và các dây dẫn trong bộ não của tôi đã vượt qua # 2.

+0

Các lớp chưa đặt tên là tiêu chuẩn C++ và đôi khi được gọi là "ẩn danh" thay vì "chưa đặt tên". –

+0

@Roger, Những gì tôi nói là chính xác. Tôi đã nói ẩn danh ** cấu trúc **; không phải là các lớp ** ẩn danh **. Các lớp ẩn danh là một phần của tiêu chuẩn C++. Cấu trúc ẩn danh là một điều C, và không phải là một phần của C++ (mặc dù chúng được mở rộng hỗ trợ nhà cung cấp rộng rãi, bao gồm cả VC). –

+0

"Cấu trúc là lớp được xác định với cấu trúc khóa lớp ..." [9/4] ** Cấu trúc là các lớp. ** –