2013-03-14 40 views
7

xem xét mã C++ sau:Làm thế nào để khởi tạo biến thành viên tham chiếu của một lớp?

#include<iostream> 

using namespace std; 

class Test { 
    int &t; 
public: 
    Test (int &x) { t = x; } 
    int getT() { return t; } 
}; 

int main() 
{ 
    int x = 20; 
    Test t1(x); 
    cout << t1.getT() << " "; 
    x = 30; 
    cout << t1.getT() << endl; 
    return 0; 
} 

Nó được thể hiện lỗi sau khi sử dụng trình biên dịch gcc

est.cpp: In constructor ‘Test::Test(int&)’: 
    est.cpp:8:5: error: uninitialized reference member ‘Test::t’ [-fpermissive] 

Tại sao không trình biên dịch trực tiếp gọi Constructor?

+0

Trong khi câu trả lời giải thích cách giải quyết vấn đề này, tôi muốn chỉ ra rằng vấn đề cơ bản là khởi tạo thực sự xảy ra _before_ phần thân của hàm tạo được nhập, để đảm bảo tất cả các thành viên đang ở trạng thái hợp lệ trước khi được sử dụng. Vì tài liệu tham khảo ** phải ** được khởi tạo, và không thể được "nhắm mục tiêu lại" sau khi khởi tạo, chúng cần phải được trỏ đến một biến thực tế trước khi phần thân của hàm tạo được nhập vào. –

Trả lời

18

Đó là do tham chiếu chỉ có thể được khởi tạo trong danh sách bộ khởi tạo. Sử dụng

Test (int &x) : t(x) {} 

Để giải thích: Chỉ có thể đặt tham chiếu một lần, nơi điều này xảy ra là danh sách bộ khởi tạo. Sau khi thực hiện xong, bạn không thể đặt tham chiếu, nhưng chỉ gán giá trị cho cá thể được tham chiếu. Mã của bạn có nghĩa là, bạn đã cố gán một thứ gì đó cho một cá thể được tham chiếu nhưng tham chiếu chưa bao giờ được khởi tạo, do đó nó không tham chiếu đến bất kỳ cá thể nào của int và bạn nhận được lỗi.

+0

Chúng cũng có thể được khởi tạo thông qua bộ khởi tạo * brace-hoặc-equalizer *, mặc dù đó sẽ là trường hợp sử dụng không phổ biến –

2

trình biên dịch của tôi phát ra lỗi này:

error C2758: 'Test::t' : must be initialized in constructor base/member initializer list

Và đó là chính xác những gì bạn phải làm. Tài liệu tham khảo phải được khởi tạo trong danh sách initializer:

#include<iostream> 

using namespace std; 

class Test { 
    int &t; 
public: 
    Test (int &x) : t(x) { } // <-- initializer list used, empty body now 
    int getT() { return t; } 
}; 

int main() 
{ 
    int x = 20; 
    Test t1(x); 
    cout << t1.getT() << " "; 
    x = 30; 
    cout << t1.getT() << endl; 
    return 0; 
} 

Giải thích:

Nếu tham chiếu không nằm trong danh sách initiliazer, đó là bên cạnh không thể đối với trình biên dịch để phát hiện nếu tham chiếu được khởi tạo. Tài liệu tham khảo phải được khởi tạo. Hãy tưởng tượng kịch bản này:

Test (int &x, bool b) 
{ 
    if(b) t = x; 
} 

Bây giờ, tùy thuộc vào người gọi hàm tạo để quyết định xem mã hợp lệ có được tạo hay không. Mà không thể được. Trình biên dịch phải đảm bảo tham chiếu được khởi tạo tại thời gian biên dịch.

+4

Chưa kể thực tế là 't = x' là ** không ** tham chiếu khởi tạo. Đó là một nhiệm vụ. Đối với tài liệu tham khảo, đây là * rất khác nhau: * initialisation liên kết tham chiếu đến một đối tượng, gán gán vào đối tượng mà tham chiếu bị ràng buộc. – Angew

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