2011-11-24 40 views
8

Tôi phải viết hàm tạo với hai tham số mặc định.cách bỏ qua Đối số Mặc định C++?

func(int arg1 , char* arg2 = "arg2", int arg3 = 1) //example 

tôi cung cấp các kịch bản mà các nhà xây dựng được gọi và một giá trị được trao cho arg1arg2arg3 dự kiến ​​sẽ sử dụng giá trị mặc định. Sau đó, một đối tượng khác được khởi tạo và một giá trị được gán cho arg1arg3 và giá trị mặc định cho arg2 được dự kiến ​​sẽ được sử dụng. Bây giờ vấn đề là, bạn "không thể bỏ qua" các tham số mặc định là những gì tôi đang đọc từ văn bản và trực tuyến. Nó nói để đặt hàng các paramters mặc định từ tính thích hợp của nó bị quá tải, nhưng kịch bản có một tham số mặc định được sử dụng trong khi khác không phải là. Các gợi ý cho câu hỏi này yêu cầu tôi sắp xếp lại các tham số/đối số. Tuy nhiên, không có số lượng sắp xếp lại mà tôi đã thực hiện dường như có thể giải quyết vấn đề này.

Ngoài ra, các nhà xây dựng quá tải không thể sử dụng được. Điều này phải được thực hiện bởi một nhà xây dựng.

Vậy làm cách nào để thực hiện việc này? Tôi bối rối và đi một chút điên trên này :(

+6

Bạn không thể làm điều này trong C++ với định nghĩa hàm đơn. Cho rằng bất kỳ giải pháp khác vi phạm những hạn chế kỳ lạ bạn có, những gì bạn muốn là không thể. Có lẽ bạn có thể sử dụng một ngôn ngữ khác. –

+1

là bài tập về nhà này? – xmoex

+0

Bạn không thể sử dụng 'vectơ' của' đối tượng '? Bằng cách này bạn có thể vượt qua những gì bạn muốn và sắp xếp những gì không được thông qua dựa trên các mục 'null'. – MoonKnight

Trả lời

6

Ngoài ra, nhà thầu bị quá tải không thể được sử dụng. Điều này đã được thực hiện bởi một nhà xây dựng.

Lý do duy nhất tôi có thể nghĩ đến trong trường hợp đó, bạn đang mắc kẹt và bạn sẽ muốn nhìn vào các thành ngữ named constructor và/hoặc named parameter.

Nếu không, chỉ cần xác định hàm tạo bổ sung. có thể liên quan đến một số giá trị mặc định trùng lặp, giá trị mặc định

Foo(int arg1 , char const *arg2 = "arg2", int arg3 = 1) 
{ 
    construct(arg1, arg2, arg3); 
} 

Foo(int arg1, int arg3) 
{ 
    construct(arg1, "arg2", arg3); 
} 
+1

Đó là một số thành ngữ thực sự tốt đẹp, nhờ chia sẻ các liên kết. Một trong những điều tuyệt vời về Stack Overflow là bạn có thể ngẫu nhiên tìm hiểu các chủ đề và tìm hiểu một số điều thú vị :) +1 –

0

Hạn chế đặc biệt, rằng chỉ phải có một hàm tạo. Dưới đây là gần nhất tôi có thể nghĩ đến:

#include <iostream> 

// cheap and cheerful Boost.Variant 
struct StringOrInt { 
    char *s; 
    int i; 
    bool is_string; 
    StringOrInt(char *s) : s(s), i(0), is_string(true) {} 
    StringOrInt(int i) : s(0), i(i), is_string(false) {} 
    bool isInt() { return !is_string; } 
    int asInt() { return i; } 
    char *asString() { return s; } 
}; 

struct Foo { 
    int m1; 
    char *m2; 
    int m3; 
    Foo(int arg1, StringOrInt arg2 = "arg2", int arg3 = 1) : m1(arg1) { 
     if (arg2.isInt()) { 
      arg3 = arg2.asInt(); 
      arg2 = "arg2"; 
     } 
     m2 = arg2.asString(); 
     m3 = arg3; 
    } 
    void print() { 
     std::cout << m1 << " " << m2 << " " << m3 << "\n"; 
    } 
}; 

int main() { 
    Foo(1, "HelloWorld").print(); 
    Foo(1, 2).print(); 
} 

Lưu ý rằng với GCC này tạo ra cảnh báo, kể từ khi chuyển đổi từ một chuỗi chữ để không const char* bị phản đối và không khôn ngoan. Nhưng đó là những gì bạn yêu cầu, và sửa chữa nó để các thông số char* và dữ liệu thành viên là const char* là dễ dàng đủ.

Điểm yếu đáng kể là điều này không ngăn bạn viết Foo(1,2,3). Để kiểm tra tại thời điểm biên dịch, tôi nghĩ bạn cần nhiều hàm tạo. Để kiểm tra nó trong thời gian chạy, bạn có thể đặt tham số thứ ba vào một lớp khác, DefaultOrInt, trong đó Default là loại được sử dụng chỉ cho mục đích này, chỉ hỗ trợ một giá trị được sử dụng làm giá trị mặc định là arg3. Sau đó, nếu arg2.isInt() là đúng, hãy kiểm tra arg3.isInt() là sai và nếu không được ném logic_error.

0

Nếu bạn được phép chuyển một chuỗi C trống khi bạn không có giá trị cho tham số thứ hai, bạn có thể sử dụng trình trợ giúp để kiểm tra arg2 và trả về giá trị mặc định nếu nó trống. Một cái gì đó như thế này:

#define DEFAULT_ARG "arg2" 

struct helper_class { 
    char* operator()(char* arg) 
    { 
     if (*arg) return arg; else return DEFAULT_ARG; 
    } 
} helper; 

class func { 
    public: 
    func(int arg1 , char* arg2 = "arg2", int arg3 = 1) {} 
}; 

int main() 
{ 
    func f1(42, helper(""), 9001); // default 2nd argument 
    func f2(42, helper("Its over 9000!")); 
} 

Không xinh đẹp, tôi biết ...

0

Ngay bây giờ bạn có thể sử dụng std::bind để làm điều này loại hoạt động hoặc trong C++ 14/17 bạn có thể sử dụng chức năng lambda và hoàn thành giống nhau.

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