2013-10-22 19 views
10

Nói rằng tôi có các lớp:Khi kế thừa từ một lớp cơ sở, điều gì sẽ xảy ra với các lớp lồng nhau?

class Base 
{ 
    public: 

     class Foo { ... }; 

     ... 
}; 

Sau đó, một lớp khác xuất phát từ cơ sở:

class Derived : public Base 
{ 
    // no mention or redefinition of nested class "Foo" anywhere in "Derived" 
}; 

này có nghĩa là chúng ta bây giờ có một khác biệt Derived::Foo, hoặc là Derived::Foo chính xác giống như Base::Foo?

Đây là một bước ngoặt về tình huống này: nếu ai đó ném một phiên bản Derived::Foo thì sao? nó sẽ được bắt gặp trong kịch bản này:

catch (const Base::Foo &ex) 
{ 
    // would this also catch an instance of Derived::Foo? 
} 

Trả lời

2

Base::FooDerived::Foo có thực sự giống nhau loại, một lớp chỉ là một loại hợp chất (từ draft C++ standard phần 3.9.2) và chúng tôi sẽ không mong đợi một loại kế thừa từ một cơ sở lớp là loại khác trong lớp có nguồn gốc có nguồn gốc. Ví dụ, nếu Base chứa:

typedef int newType1 ; 

càng lâu càng Derived không redeclare newType1 sau đó chúng tôi mong chờ Base::newType1Derived::newType1 để được giống loạilồng lớp là không khác nhau. Nếu chúng ta hãy tham khảo phần dự thảo tiêu chuẩn 9.2thành viên Lớp đoạn nói (tôi nhấn mạnh):

[...] thành viên của một lớp là thành viên dữ liệu, chức năng thành viên (9,3), các loại lồng nhau và điều tra viên. Các thành viên dữ liệu và các hàm thành viên là tĩnh hoặc không tĩnh; xem 9.4. Các loại lồng nhau là lớp (9.1, 9.7) và liệt kê (7.2) được xác định trong lớp, và các loại tùy ý được khai báo là thành viên bằng cách sử dụng khai báo typedef (7.1.3).

Điều đó khẳng định trực giác rằng lớp lồng nhau chỉ loại (và cũng có thể các thành viên), cho phần hoàn thiện vì lợi ích 9.7 tham chiếu ở trên là lồng lớp phần và từ phần 10lớp Derived đoạn , chúng tôi thấy:

[...] Trừ khi được redeclared trong lớp dẫn xuất, thành viên của lớp cơ sở là cũng được coi là thành viên của lớp phái sinh. [...]

Vì chúng cùng loại bắt sẽ hoạt động tốt.

10

Derived::Foo chỉ được truy cập vào Base::Foo, do đó đây chỉ là hai cách để tham khảo cùng loại. Bạn có thể dễ dàng kiểm tra nó với std::is_same:

#include <type_traits> 

struct Base 
{ 
    class Foo {}; 
}; 

struct Derived : Base {}; 

static_assert(std::is_same< Base::Foo, Derived::Foo >::value, "Oops"); 

int main() 
{ 
    try { 
     throw Derived::Foo(); 
    } 
    catch(const Base::Foo&) {} 
} 

Như bạn có thể thấy, đây cũng có nghĩa là ném nó bằng một cái tên và bắt nó bằng cách thức hoạt động khác nữa.

Live example

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