如果我有一個構造函數,其中有2個必需的參數和4個可選參數,我該如何避免編寫16個構造函數或者10個左右的構造函數,如果我使用默認參數我不喜歡它,因爲這是糟糕的自我文檔)?有沒有使用模板的習語或方法,我可以用它來減少繁瑣? (更容易維護?)避免可選參數的枯燥
回答
您可能會感興趣Named Parameter Idiom。
總而言之,創建一個類來保存要傳遞給構造函數的值。添加一個方法來設置每個值,並使每個方法在末尾執行return *this;
。在你的類中有一個構造函數,它接受一個對這個新類的const引用。這可以像這樣使用:
class Person;
class PersonOptions
{
friend class Person;
string name_;
int age_;
char gender_;
public:
PersonOptions() :
age_(0),
gender_('U')
{}
PersonOptions& name(const string& n) { name_ = n; return *this; }
PersonOptions& age(int a) { age_ = a; return *this; }
PersonOptions& gender(char g) { gender_ = g; return *this; }
};
class Person
{
string name_;
int age_;
char gender_;
public:
Person(const PersonOptions& opts) :
name_(opts.name_),
age_(opts.age_),
gender_(opts.gender_)
{}
};
Person p = PersonOptions().name("George").age(57).gender('M');
你將如何在構造函數中完成這項工作?通過在構造方法中使用'return this'? – 2010-04-23 18:21:22
顯然,你不能從構造函數中返回任何東西。但是您可以使用一個副本,例如'Foo f = Foo()。option1()。option2();'。鏈接中的示例使用單獨的類來進行實際創建。 – 2010-04-23 18:27:14
@Robert重要的是要注意右側以'PersonOptions'開頭,而不是'Person'。這創建了一個大概是輕量級的對象,然後有許多方法調用來將屬性設置爲非默認值。然後有一個名爲'Person(const PersonOptions&)'和ta da的ctor。一個對象的實例化(例如'PersonOptions()')在當前上下文中保留「* this」,所以你可以立即使用.method()方法。儘管如此,每個方法仍然需要'return * this'才能鏈接。 – 2010-04-23 18:48:24
如果您製作了一個包含所有字段的參數對象,該怎麼辦?那麼你可以通過它,只需設置你需要的任何領域。有可能是該模式的名稱,不知道它是什麼,但...
UPDATE:
代碼可能看起來有點這樣的:
paramObj.x=1;
paramObj.y=2;
paramObj.z=3;
paramObj.magic=true;
... //set many other "parameters here"
someObject myObject = new someObject(paramObj);
和someObject
構造函數中,你可以爲尚未設置的事件設置默認值(如果是強制性的,則會產生錯誤)。
老實說,我不是這個解決方案的忠實粉絲,但是我已經使用過一兩次,因爲paramObj
通過包含一組通常所有的數據都是合理的(所以我們可以將它用於超過只是構造函數),它比多個構造函數更好。我發現它很醜,但它工作,YMMV。
...並且此參數對象將在其默認構造函數中設置默認值。 – Danvil 2010-04-23 18:22:45
爲什麼這比僅僅構建原始對象和設置屬性更好? – 2010-04-23 18:25:05
@Johannes:這不就是弗雷德拉森在他的回答中提到的命名參數成語嗎? – 2010-04-23 18:27:05
而現在,爲「加速有它的東西」的答案:
的Boost Parameter Library似乎是一個很好的適合你的使用情況。
所有新的C++ 17
#include <optional>
using optional_int = std::optional<int>;
class foo {
int arg0, arg1; // required
int arg2, arg3; // optional
const int default_2 = -2;
const int default_3 = -3;
public:
foo(int arg0, int arg1, optional_int opt0 = {}, optional_int opt1 = {})
: arg0(arg0), arg1(arg1)
, arg2(opt0.value_or(default_2))
, arg3(opt1.value_or(default_3))
{ }
};
int main() {
foo bar(42, 43, {}, 45); // Take default for opt0 (arg2)
return 0;
}
我有一個三次樣條實現,它允許用戶可選地在任一左端,右端,或兩者指定一階導數。如果未指定導數,則實際的代碼通過假定二階導數爲零(即所謂的「自然樣條」)來計算一個導數。這是一個左端的片段。
// Calculate the second derivative at the left end point
if (!left_deriv.has_value()) {
ddy[0]=u[0]=0.0; // "Natural spline"
} else {
const real yP0 = left_deriv.value();
ddy[0] = -0.5;
u[0]=(3.0/(x[1]-x[0]))*((y[1]-y[0])/(x[1]-x[0])-yP0);
}
- 1. 避免將未定義的可選參數
- 2. 如何避免在python中使用特定的可選參數
- 3. 使用Python自動化枯燥的東西。逗號碼
- 4. 如何使功能參數可選(以避免每次調用所有參數)
- 5. 避免與靜態參數
- 6. 避免通用參數
- 7. 乾燥參數檢查
- 8. 如何避免C中的「self」參數?
- 9. 如何避免if語句在獲取可選參數的方法中
- 10. 如何在編寫接受可選參數的裝飾器時避免「()」?
- 11. 避免選擇onClick
- 12. 避免over_query_limit許可
- 13. 如何避免將空參數傳遞給具有多個可選參數的函數?
- 14. 如何避免模板參數推導
- 15. 檢查參數,以避免try..catch塊(?)
- 16. 如何避免所有參數?
- 17. 日誌聲明避免計算參數
- 18. 避免模板轉換參數
- 19. 避免重新分配參數
- 20. 如何避免輸出參數?
- 21. SQL查詢,以避免空值參數
- 22. 追加參數到URL,避免重複
- 23. 如何避免指定類型參數
- 24. 避免將選項自動作爲參數
- 25. 如何避免24 IF語句選項SQL查詢參數
- 26. 避免循環參考
- 27. 的jQuery可排序:避免
- 28. 不可避免的崩潰
- 29. 可變參數模板 - 是有辦法避免重複
- 30. 乾燥軌道控制器,以避免重複多次相同的方法
你確定你的班級沒有嘗試做太多嗎? – 2010-04-23 18:20:22
@Johannes:他希望跳過說d的可能性而不強迫調用者知道其默認值。 – Danvil 2010-04-23 18:24:57
@John:我可以看到你在看什麼,但參數可以是屬性。例如,我有一個GUI Button類,它具有很多屬性,如圖像,文本,大小,顏色等等,但我不覺得它「做得太多」。恕我直言,按鈕服務於一個非常具體的目的,很容易適應一個類,用戶將立即知道什麼課程完成。 – Kyle 2010-04-23 18:32:18