2013-04-04 32 views
11

Mã sau đây cung cấp cho tôi lỗi biên dịch 'giá trị' không được khai báo trong phạm vi này.Thành viên của mẫu lớp cơ sở nằm ngoài phạm vi trong mẫu lớp dẫn xuất có cùng một đối số mẫu

template<class T> 
struct Base { 
    int value; 
}; 

template <class T> 
struct Derived : public Base<T> { 
    int getValue() { return value; } 
}; 

tôi thấy nó vô cùng kỳ lạ mà

  • nếu Derived thừa hưởng từ Base<std::string>, mã biên dịch,
  • nếu tôi return Base<T>::value, mã biên dịch.

Tại sao mã không biên dịch như vậy? Theo cách nào là 'giá trị' không được khai báo trong phạm vi Derived<T>::getValue()?

Trả lời

16

value là một không đủ tiêu chuẩn tên, và trong giai đoạn đầu tiên của tra cứu tên, trình biên dịch sẽ không có đầu mối rằng đây là một thành viên dữ liệu kế thừa từ một lớp cơ sở (nó đã không instantiated Base<T> chưa). Do đó, nó sẽ tìm kiếm không gian tên chung và không tìm thấy biến nào được gọi là value; do đó, nó sẽ phát ra một lỗi.

Đây là một cách tiếp cận điển hình để giải quyết vấn đề này:

template <class T> 
struct Derived : public Base<T> { 
    int getValue() { return this->value; } 
    //      ^^^^^^ 
}; 

explictly dereferencing this nói với trình biên dịch rằng tên sau đây là tên của một (có thể thừa hưởng) thành viên dữ liệu và tra cứu nên được trì hoãn đến điểm mà chức năng thành viên thực sự được khởi tạo. Tất nhiên, giải pháp của bạn làm:

return Base<T>::value; 

cũng không kém phần tốt, bởi vì nó cũng nói với trình biên dịch rằng value được thừa kế từ lớp cơ sở Base<T>.

Đối với những gì liên quan đến phát sinh từ Base<std::string>, trình biên dịch ngay lập tức có thể đi và nhìn lên dù Base<std::string> chứa một thành viên dữ liệu có tên value (vì nó không phụ thuộc vào bất kỳ mẫu tham số) và nếu đúng như vậy, nó sẽ có thể xác định rằng biểu thức được định dạng tốt.

Tuy nhiên, nếu lớp cơ sở của bạn là Base<T>, nơi T là chưa biết trong giai đoạn đầu tiên của tra cứu tên, trình biên dịch có thể không nói value là gì (chuyên ngành của Base cho khác nhau T s có thể thậm chí không có value tại tất cả) .

Đoạn 14,6/3 của C++ 11 Tiêu chuẩn:

Trong định nghĩa của một lớp hoặc lớp mẫu, nếu một lớp cơ sở phụ thuộc vào một mẫu tham số, phạm vi lớp cơ sở không phải là kiểm tra trong quá trình tra cứu tên không đủ tiêu chuẩn hoặc tại điểm định nghĩa của mẫu lớp hoặc thành viên hoặc trong quá trình khởi tạo mẫu hoặc thành viên lớp. [...] [Ví dụ:

struct A { 
    struct B {/.../}; 
    int a; 
    int Y; 
}; 

int a; 

    template<class T> struct Y : T { 
    struct B {/.../}; 
    B b; // The B defined in Y 
    void f(int i) { a = i; } // ::a 
    Y* p; // Y<T> 
    }; 

Y<A> ya; 

Các thành viên A::B, A::a, và A::Y của mẫu luận A không ảnh hưởng đến các ràng buộc của tên trong Y<A>. - ví dụ kết thúc]

+0

Câu trả lời hay. – Oswald

+0

@Oswald: Cảm ơn bạn, vui vì tôi có thể giúp –

+0

Tuyệt vời, như mọi khi tôi có thể thêm :). –

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