使用参数列表将参数传递给父级

时间:2017-08-31 08:23:53

标签: c++ parameters overloading

考虑我们有两个类:

#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 ++不支持使用init参数列表重载。对此有何解决方法?

2 个答案:

答案 0 :(得分:1)

重载函数必须具有不同的参数列表或const / not-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;
    }
}

答案 1 :(得分:0)

它不能重载DerivedWithParams,因为编译器不知道选择哪个实现。 如果你用DerivedWithParams foo( &myParams );来调用它会选择哪一个? 你需要做点什么来区分这两者。