2010-06-15 40 views
8

Tôi có cấu trúc Foo. Trong mã giả:C++: Trả về NULL thay vì struct

def FindFoo: 
    foo = results of search 
    foundFoo = true if a valid foo has been found 

    return foo if foundFoo else someErrorCode 

Tôi có thể thực hiện điều này bằng C++ bằng cách nào?

Đã chỉnh sửa để loại bỏ nhiều điểm không chính xác.

+0

Loại trả lại của bạn không nhất quán. Nếu tìm kiếm thành công, nó là 'Foo &'; nếu nó không thành công, đó là 'ErrorCode'. Một giải pháp cho vấn đề này là trả về một 'Foo *', trỏ đến phần tử đã được tìm thấy, hoặc là NULL nếu không tìm thấy phần tử nào. – pyon

Trả lời

12

Đối tượng C++ không được rỗng hoặc trống. Con trỏ có thể giữ một giá trị con trỏ null cho biết chúng trỏ vào không có gì.

Giải pháp điển hình là ném ngoại lệ. Nếu không, hãy sử dụng một con trỏ; chỉ cần đảm bảo bạn không trả lại địa chỉ tạm thời.

Tôi không khuyên bạn nên cố gắng tự dạy cho mình C++ với kiến ​​thức từ các ngôn ngữ khác, bạn sẽ tự làm tổn thương bản thân. Lấy một good beginner-level book, đó là cách tốt nhất để tìm hiểu.

+7

+1 cho "Tôi không khuyến khích cố gắng tự dạy cho mình C++ với kiến ​​thức từ các ngôn ngữ khác" –

+1

Tôi nghĩ giải pháp điển hình là bắt chước STL một iterator giống như đối tượng trỏ đến các đối tượng không hợp lệ (một trong quá khứ ở cuối container). –

+0

@Martin: Tôi sẽ chỉ nói đó là một con trỏ tổng quát hơn và gặp bạn một nửa. : P – GManNickG

1

Điều đó cũng không hoạt động trong C#. Bạn nên trả về một con trỏ đến Foo.

+3

@Dura, câu hỏi là "Làm thế nào tôi có thể thực hiện điều này trong C++?" –

+0

Nó cũng có thẻ C#! – nevets1219

0

Bạn không thể thực hiện việc này trong C# - bạn sẽ cần phải trả lại new Foo(), không phải null để làm cho trình biên dịch hài lòng.

Ditto trường hợp C++ - bạn cần khởi tạo cấu trúc nếu bạn định trả về giá trị. Nếu không, bạn muốn trở lại bằng con trỏ (trong trường hợp này bạn sẽ là new ing hoặc trả về một con trỏ đến một được cấp phát theo cách khác, mang lại ngữ nghĩa chuyển quyền sở hữu lộn xộn vào phương trình).

CHỈNH SỬA: Dựa trên cập nhật của bạn. Có vẻ như bạn muốn trả lại giá trị hoặc giá trị meta 'null' cho biết 'không tìm thấy'. Bạn có thể làm điều này trong một số cách:

  1. throw nếu nó không thành công, nếu không vô điều kiện trả về giá trị
  2. trở lại một con trỏ - nhưng điều này rời khỏi trách nhiệm về delet ing nó lên trong không khí nếu nó không phải là một cái gì đó nó sẽ nằm trong bộ nhớ dài hạn
  3. quấn nó vào đối tượng bao bọc [templated] xử lý điều kiện theo cùng cách mà .NET Nullable<T> sẽ (Tôi sẽ để ai đó gọi vào đúng UPDATE: @Mike Seymour nói rằng đó là boost::optional<foo>)
  4. sử dụng đối tượng Null attern để trả lại một giá trị thích hợp mà làm điều đúng đắn khi đối xử như một resut hợp lệ trên các mặt hàng
1

Một cách để làm việc đó là để trả về một con trỏ đến một foo:

public Foo* findFoo() 
{ 
    return fooFound ? new fooResult() : NULL; 
} 

Một khả năng khác để xác định một loại NullFoo thuộc loại nào đó, có thể là struct mở rộng Foo khi triển khai trống. Để biết thêm thông tin về ý tưởng sau, bạn có thể đọc về số Null Object Pattern.

Chỉnh sửa: Câu hỏi được sửa đổi hơi khác và như những người khác đã đề cập, bạn có thể nên loại bỏ ngoại lệ tốt hơn là thực hiện một trong hai điều trên.

+0

fooFound chỉ là điều kiện để kiểm tra, fooResult là những gì được trả về. –

+1

Khả năng khác là 'tăng :: tùy chọn '. Sau đó, bạn không cần phải nhớ để xóa nó. –

+0

@Mike Seymour: Cảm ơn - nài nỉ rằng để hoàn thành câu trả lời của tôi # 3 –

1

Không thể thực hiện trong C++ mà không cần trỏ đến con trỏ hoặc giải pháp thư viện bên ngoài thư viện chuẩn.(Tăng không phải là một phần của thư viện chuẩn, đó là giải pháp của bên thứ ba.)

Trong C#, bạn có thể sử dụng Nullable<Foo>.

Trái ngược với ý kiến ​​của Billy, cấu trúc là kiểu giá trị, không tham khảo các loại, và Nullable có thể được áp dụng cho bất kỳ loại giá trị, không chỉ built-in. Các bản dịch sau đây chỉ tốt:

struct Test { 
    int Blah; 
} 
void Main() { 
    System.Nullable<Test> proof; 
} 
+0

Không, bạn không thể. Trước hết, Nullable chỉ hợp lệ trên các kiểu nội bộ, không phải trên các kiểu do người dùng định nghĩa như 'Foo'. Thứ hai, ngay cả khi nó là hợp lệ, nó sẽ không giúp bạn anyway bởi vì tham chiếu đối tượng có thể đã được null. Và cuối cùng, OP yêu cầu trả lại mã lỗi, chứ không phải NULL. –

+0

@Billy: Dễ dàng trên -1 giây. struct có nghĩa là loại giá trị, không tham chiếu và bạn có thể làm một kiểu giá trị nullable - đó là toàn bộ điểm –

+0

+1 thực tế chính xác lại .NET. Ditto bit C++, mặc dù bỏ qua các cách xung quanh thả xuống con trỏ [như mô hình đối tượng Null, ném, gói trong một tăng :: tùy chọn]. + 1ing là câu trả lời không tắt chủ đề hoặc không chính xác. Hơn nữa irellevant và câu trả lời chưa đầy đủ đã được upvoted ở đây. –

4

Ném ngoại lệ. Đó là những gì họ đang cho.

3

Bạn có thể xem xét boost::optional và xem liệu nó có phù hợp với nhu cầu của bạn hay không. Tuy nhiên:

trở foo nếu foundFoo khác someErrorCode

này khiến tôi nghĩ rằng bạn có thể được tốt hơn off ném một ngoại lệ nếu bạn không tìm thấy foo.

1

Không tìm thấy một foo thực sự là một tình huống đặc biệt? Sau đó ném một ngoại lệ. Hy vọng không tìm thấy foo? có hàm trả về mã lỗi và chuyển foo ra thông qua tham số tham chiếu, trong đó foo chỉ hợp lệ nếu hàm trả về không có lỗi.

+0

Đó sẽ là cách tiếp cận của tôi. Giữ mọi thứ đơn giản và phụ thuộc tối thiểu. –