2012-01-29 26 views
17

Có thể khởi tạo thành viên tham chiếu thành NULL bằng C++ không?
Tôi đang cố gắng một cái gì đó như thế này:Khởi tạo tham chiếu đến thành viên thành NULL bằng C++

class BigClass 
{ 
private: 
    Object m_inner; 
public: 
    const Object& ReadOnly; 
    BigClass() : ReadOnly(NULL) 
    { 
    Do stuff. 
    } 
}; 

Tôi biết tôi có thể làm điều này nếu tôi khởi tạo "ReadOnly" tới tài liệu tham khảo thực sự của một đối tượng, nhưng khi tôi muốn đặt ở đó "NULL", tôi gặp lỗi:

"cannot convert from 'int' to 'const Object &'

Làm cách nào để giải quyết vấn đề này?

+6

Điểm tham chiếu là làm điều này là không thể. Thay vào đó, hãy sử dụng con trỏ thông thường. –

+0

Bạn có thể làm điều này { const Object & ReadOnly = \ * (Object \ *) NULL; } Nhưng tính cách của nó. Bộ xử lý trước chỉ cần xóa & & \ * – Justin

+0

@Justin "_Bộ xử lý trước chỉ xóa bỏ & và * _" vô nghĩa – curiousguy

Trả lời

23

Không, tham chiếu không được là NULL bằng C++.

giải pháp có thể bao gồm:

  • sử dụng một con trỏ thay vì một tài liệu tham khảo.
  • có mẫu giả Object có thể được sử dụng để biểu thị "không có đối tượng".

[1] Từ C++11 standard:

[dcl.ref] [...] a null reference cannot exist in a well-defined program, because the only way to create such a reference would be to bind it to the “object” obtained by dereferencing a null pointer, which causes undefined behavior.

+0

@Magnus: Vâng, đừng làm, đó là hành vi không xác định. – Xeo

+0

Sử dụng con trỏ 'const'. – curiousguy

+0

Không, đó là sai! – wandalen

9

Bạn không thể "giải quyết" này. Sử dụng một con trỏ nếu bạn muốn để có thể có thành viên đó không trỏ đến bất cứ điều gì.

Tài liệu tham khảo phải được khởi tạo cho một đối tượng thực, chúng không thể "trỏ đến đâu cả".

+0

Hoặc tốt hơn, hãy sử dụng một con trỏ thông minh. – Lalaland

+4

@EthanSteinberg: phụ thuộc. Con trỏ thông minh thường liên quan đến quyền sở hữu. Đôi khi bạn chỉ muốn trỏ đến một cái gì đó mà không yêu cầu quyền sở hữu. Tất nhiên bạn có thể sử dụng một con trỏ yếu, nhưng điều này đòi hỏi phải phân bổ đối tượng trên heap: không có đối tượng phân bổ stack, không có thuộc tính của một đối tượng lớn hơn, vv ... * Smart Pointers là ** NOT ** a panacea *. –

1

Sử dụng con trỏ: - const Object * pReadOnly;

5

Nó có thể được thực hiện nhưng nó gần như chắc chắn là một ý tưởng cực kỳ tồi tệ . Cách để làm điều đó là để dereference một con trỏ NULL phù hợp đã cho thấy rằng đó là một ý tưởng tồi: bạn đến hành vi không xác định tại thời điểm này, tuy nhiên, thường có xu hướng "làm việc".

Trong tài liệu tham khảo C++ có nghĩa là luôn đề cập đến một đối tượng thực tế. Điều này khác với các ngôn ngữ lập trình khác trong đó "tham chiếu" thực sự tương đương với con trỏ bằng C++ (thường không có những thứ như số học con trỏ). Những gì bạn có thể thực sự muốn (bạn không may nói những gì bạn cố gắng đạt được nhưng được hỏi về giải pháp cho một vấn đề có thể là một phần của cách tiếp cận sai lầm) là sử dụng con trỏ thay thế:

Object const* const readOnly; 
BigClass(): readOnly(0) {} 
+0

Câu trả lời yêu thích của tôi. Tôi chỉ cần gỡ lỗi một lớp phức tạp và cần gọi một hàm duy nhất, với một đối tượng nhất định. 0 tham chiếu tất cả các tham chiếu như mô tả, obj được xây dựng, các tham chiếu bị bỏ qua, được gọi là hàm, cố định vấn đề, xóa mọi thứ. Rõ ràng không phải cái gì bạn muốn làm vĩnh viễn mặc dù. – Cookie

1

hữu ích trong việc viết đơn vị kiểm tra. Đó là chỉ nơi cần được thực hiện, nhưng ở đó, nó khá hữu ích.

Bar& bar(*static_cast<Bar*>(0)); 
MockClass mock; // derives from RealClass 
mock.foo(bar); 

Ở đây, tôi đang thử nghiệm mã sử dụng MockClass chính nó.

Nó không phải là thuốc chữa bách bệnh, nhưng nó có thể hữu ích. Ngoài ra, GoogleMock có thể là bạn của bạn nếu bạn đang chế nhạo các lớp "cụ thể".

struct Bar; 
struct RealClass { 
    int& x_; 
    double& y_; 
    RealClass(int& x, double& y) :x_(x), y_(y) {} 
    virtual void foo(Bar&); 
}; 
struct MockClass: public RealClass { 
    MockClass(): RealClass(*(int*)0, *(double*)0) {} 
    MOCK_METHOD1(foo, void(Bar&)); 
}; 
+0

Down-cử tri: Hãy thử điều này * mà không * bằng cách sử dụng một tham chiếu đến NULL. Rất khó! Trong trường hợp không rõ ràng, chúng tôi hướng đến việc kiểm tra mã sử dụng 'RealClass' và gọi' foo() 'trên' RealClass' đó. Chúng tôi tiêm cả hai trường hợp 'RealClass' và' Bar'. 'MockClass' cần gọi hàm tạo của' RealClass', nhưng dữ liệu cơ bản không bao giờ cần thiết. Đây là trường hợp sử dụng hợp lệ, vì vậy hãy ngừng bỏ phiếu xuống. – cdunn2001

+0

Nếu bạn cần viết loại thử nghiệm này, tôi nghĩ bạn có vấn đề thiết kế nghiêm trọng. – Nax

+1

Nó được gọi là mã di sản, bạn của tôi. – cdunn2001

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