2017-08-31 36 views
-2

考慮,我們有兩大類:參數傳遞給家長與參數列表

#include<iostream> 
using namespace std; 
class Base { 
public: 
    Base(char c) { 
     cout << __FUNCTION__ <<":"<<__LINE__ << endl; 
    } 
    Base(double d) { 
     cout << __FUNCTION__ <<":"<<__LINE__ << endl; 
    } 
    ~Base() { 
     cout << __FUNCTION__ <<":"<<__LINE__ << endl; 
    } 
}; 
class Derived: public Base{ 
    public: 
    Derived(int i, float f, char c):Base(c) { 
     cout << __FUNCTION__ <<":"<<__LINE__ << endl; 
    } 
    Derived(int i, float f, double d):Base(d) { 
     cout << __FUNCTION__ <<":"<<__LINE__ << endl; 
    } 
    ~Derived() { 
     cout << __FUNCTION__ <<":"<<__LINE__ << endl; 
    } 
}; 

這很簡單,易於理解。現在,我們要實現一個新的類DerivedWithParams:

class DerivedWithParams : public Base{ 
public: 
    struct Params { 
     int i; 
     int f; 
     char c; 
     double d; 
    }; 
    DerivedWithParams(Params* params):Base(params->c) { 
     cout << __FUNCTION__ <<":"<<__LINE__ << endl; 
    } 
    DerivedWithParams(Params* params):Base(params->d) { 
     cout << __FUNCTION__ <<":"<<__LINE__ << endl; 
    } 
    ~DerivedWithParams() { 
     cout << __FUNCTION__ <<":"<<__LINE__ << endl; 
    } 
}; 

然而,在編譯時,它抱怨: 不能超載

看來C++不支持初始化參數列表超載。任何解決方法?

+3

C++支持重載,但您需要更改簽名。你的兩個構造函數具有相同的簽名。 –

+1

你有兩次'DerivedWithParams(PARAMS * PARAMS)'... – Jarod42

+0

@通過簽名tobi303 - 這包括CV-預選賽。 –

回答

0

它不能超載DerivedWithParams,因爲編譯器不知道該選擇哪實施。 如果你打電話給DerivedWithParams foo(&myParams);它會選擇哪一個? 你需要做一些事情來區分這兩者。

1

重載函數必須有不同的參數列表或是const /不常量。然而

DerivedWithParams(Params* params):Base(params->c) { 
    cout << __FUNCTION__ <<":"<<__LINE__ << endl; 
} 
DerivedWithParams(Params* params):Base(params->d) { 
    cout << __FUNCTION__ <<":"<<__LINE__ << endl; 
} 

這兩個聲明是相同的(DerivedWithParams(Params* params)),所以編譯器就沒有辦法知道哪些打電話。

如果您打算做一些樣的結構,它可以包含不同類型的值,你需要一種方法來確定它究竟包含,並與運行邏輯,例如只有一個功能

struct Params 
{ 
    enum Type 
    { 
     PARAM_I, PARAM_F, PARAM_C, PARAM_D; 
    }; 
    Type type; 
    union 
    { 
     int i; 
     int f; 
     char c; 
     double d; 
    }; 
}; 

DerivedWithParams::DerivedWithParams(Params* params) 
{ 
    switch(params->type) 
    { 
    case Params::PARAM_I: 
     std::cout << params->i << std::endl; 
     break; 
    case Params::PARAM_F: 
     std::cout << params->f << std::endl; 
     break; 
    case Params::PARAM_C: 
     std::cout << params->c << std::endl; 
     break; 
    case Params::PARAM_D: 
     std::cout << params->d << std::endl; 
     break; 
    default: 
     std::cout << "Unknown" << std::endl; 
     break; 
    } 
} 

爲C++ 17類似的功能由std::variant提供,或者你可以使用Boost C++庫boost::variant

typedef std::variant<int, char, double> Params; 
DerivedWithParams::DerivedWithParams(const Params &params) 
{ 
    if (auto val = std::get_if<int>(&params)) 
    { 
     std::cout << "int " << *val << std::endl; 
    } 
    else if (auto val = std::get_if<char>(&params)) 
    { 
     std::cout << "char " << *val << std::endl; 
    } 
    else 
    { 
     std::cout << "Unknown" << std::endl; 
     break; 
    } 
} 
+0

但是如何在這裏啓動Base(char)或Base(double)?我知道C++不支持init參數列表的超載。但是在這裏我沒有研究如何將char或double傳遞給Base構造函數。 – user8073659

+0

您可以將'Params'/variant傳遞給自己,否則不可以,因爲您只能構造一次基礎,並且必須調用特定的過載。你將不得不做一個默認的構造函數,並讓派生類設置後的東西。或者如果你只對動態分配(新/刪除)有興趣,可以做一個工廠函數,並可以調用構造函數('new Derived(char)','new Derived(int)'等),或者我想新的,但越來越複雜(查看它)。但它的所有相同的想法,'switch'或'if','else if'等等或類似必須在某處* –