2012-11-08 16 views
5

Tôi giả định rằng hàm đã có giá trị trả về để không thể thêm vào.Làm cách nào để thêm thông số đầu ra vào một hàm mà không vi phạm mã hiện tại?

Điều tôi đưa ra để giải quyết vấn đề này là thêm các tham số con trỏ bổ sung mặc định là nullptr.

Trước:

bool fun(double a, std::vector<std::randomexample> const & b) 

Sau:

bool fun(double a, std::vector<std::randomexample> const & b, int* extraoutput = nullptr) 

và sử dụng nó như thế này

if(extraoutput) 
    *extraoutput = whatever; 

Nhưng đó chỉ là những gì tôi đã đưa ra. Tôi muốn biết nếu có cách nào tốt hơn để làm điều này. Lưu ý rằng "mọi thứ" đã có trong hàm.

+1

Có vẻ hợp lý. –

+1

Nếu bạn hoàn toàn không muốn thay đổi nội dung hiện có, hãy tạo một mục đã quá tải mới. –

Trả lời

4

Nếu vì một số lý do bạn cần nhị phân cũng như (chủ yếu) nguồn tương thích [*]:

Trước:

bool fun(double a, std::vector<std::randomexample> const & b) { 
    // do stuff 
    return true; 
} 

Sau:

bool fun(double a, std::vector<std::randomexample> const & b, int* extraoutput) { 
    // do stuff 
    if(extraoutput) 
     *extraoutput = whatever; 
    return true; 
} 
bool fun(double a, std::vector<std::randomexample> const & b) { 
    return fun(a, b, nullptr); 
} 

Nếu bạn không muốn quá tải chức năng (ví dụ: nếu fun là một phần của extern "C" i nterface), sau đó bạn không thực sự phải gọi hàm mới fun. Nó cũng có thể là fun2.

[*] Như AndreyT đã chỉ ra, tính tương thích nguồn của giải pháp của bạn bị giới hạn. Các cuộc gọi đến chức năng cũ của bạn sẽ gọi hàm mới của bạn tốt, nhưng một số thứ khác mà bạn có thể làm với chức năng cũ sẽ không hoạt động tốt (vì bạn đã thay đổi loại của nó).

Thực sự không có khả năng tương thích nguồn trong mã của tôi. void(*foo)() = (void(*)()) fun; được phép trước khi quá tải được thêm vào, nhưng sau đó nó không rõ ràng. Nếu bạn muốn hỗ trợ mã thực hiện điều đó, thì đó là lý do thứ hai không muốn quá tải hàm.

+0

Tại sao loại chức năng cũ lại thay đổi? Tôi có nghĩa là, chức năng cũ bây giờ chỉ cần gọi chức năng mới để nội dung dường như đã thay đổi nhưng tôi không thấy lý do tại sao loại thay đổi. – Sarien

+0

@Corporal: loại hàm của bạn 'bool fun (double a, Foo const & b)' là 'bool (double, Foo const &)'. Kiểu hàm bool của bạn (double a, Foo const & b, int * extraoutput = nullptr) 'là' bool (double, Foo const &, int *) '. Hai là không giống nhau. Trong mã của tôi, vẫn có một hàm với kiểu 'bool (double, Foo const &)' * ngoài * hàm mới, vì vậy mã dựa trên kiểu cũ là OK. –

+0

Ah, được rồi, do đó, nó không thực sự là một vấn đề trong giải pháp của bạn mà là của tôi. Xin lỗi, đã nhầm lẫn. :) – Sarien

-1

Bạn có thể thử triển khai mẫu Observer đời sống. Dưới đây là một ví dụ: http://sourcemaking.com/design_patterns/observer

Sẽ tốt hơn cho tương lai khi bạn muốn thêm nhiều thông số hơn. Nếu bạn không thể lấy được sau đó đi qua như một tham số sẽ là giải pháp quá.

Vì tôi hiểu bạn phải làm điều đó trong chức năng này, nếu không thì tình trạng quá tải là một giải pháp tốt.

Nó không phá vỡ khả năng tương thích nhị phân nếu không với giải pháp khác.

+1

Điều này có thực sự liên quan đến trường hợp hiện tại không? –

+0

Giải pháp chung chung hơn luôn luôn là một trường hợp, tôi nghĩ cho tương lai khi có thêm thông số có thể đi vào trò chơi. – CyberGuy

+0

@Cthulhu: có thể. Thêm một tham số mới tùy chọn ngay bây giờ, hiện có chức năng 'quan sát '. Khi điều tương tự xảy ra lần nữa, bạn không phải thêm * một tham số con trỏ tùy chọn khác vào hàm, thay vào đó bạn có thể thêm một hàm khác cho người quan sát. –

0

Như đã nêu bởi những người khác, đây sẽ là sản phẩm cuối cùng của bạn.

bool fun(double a, std::vector<std::randomexample> const & b){ 
    return fun(a,b,0); 
} 
bool fun(double a, std::vector<std::randomexample> const & b, int* extraoutput = 0){ 
    // have fun! 
    if(extraoutput) *extraoutput = whatever; 
    return true; 
} 
+0

tại sao đối số mặc định? – xtofl

+1

Trong trường hợp đó, bạn phải loại bỏ đối số mặc định, vì nếu không cuộc gọi với 2 đối số sẽ trở nên mơ hồ. – AnT

+0

Có lẽ nó sẽ là ý tưởng tốt để chỉ cần tạo ra rằng extraoutput trong chức năng mới và vượt qua nó như là tài liệu tham khảo. Có thể lưu một số bản sao chép và cuộc gọi sẽ không còn mơ hồ nữa. – Sarien

2

Thông thường, tôi thêm một phương thức với các tham số phụ, và gọi đó là một với một giá trị mặc định từ phương pháp cũ:

//foo v1 
void foo(S s) { 
    ... stuff with s; 
}; 

//codeA_v1: 
S s; 
foo(s); 

//codeB_v1 
S s2; 
foo(s2); 

Sau đó, tôi thêm một phương thức với một tham số phụ:

void foo(S s){ foo(s, default_value_for_T); } 
void foo(S s, T t){ 
    ... stuff with s and t 
} 

//codeA_v1 == codeA_v2 
S s; 
foo(s); 

//codeB_v2 
S s; 
T t; 
foo(s,t); 
2

Đây là nhận xét mở rộng. Như được đề xuất bởi những người khác, bạn nên quá tải chức năng để cung cấp cả nguồn và khả năng tương thích nhị phân. Lý do để làm như vậy là bằng cách giới thiệu một thay đổi trong chữ ký chức năng, bạn cũng thay đổi tên biểu tượng bị xáo trộn, ví dụ: từ _Z3fundRKSt6vectorISt13randomexampleSaIS0_EE đến _Z3fundRKSt6vectorISt13randomexampleSaIS0_EEPi. Điều này sẽ phá vỡ khả năng tương thích nhị phân với tất cả các đối tượng khác gọi là fun() bởi tên cũ của nó. Nếu fun() là một phần của thư viện được liên kết động, nó sẽ phá vỡ tất cả các tệp nhị phân hiện có liên kết với nó vì liên kết động sẽ không thể giải quyết tham chiếu biểu tượng _Z3fundRKSt6vectorISt13randomexampleSaIS0_EE nữa. Nếu bạn đi với phiên bản chức năng quá tải, biểu tượng bị xáo trộn cũ vẫn tồn tại và khả năng tương thích nhị phân sẽ được giữ lại.

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