按返回类型重载

时间:2012-03-05 15:04:37

标签: c++ overloading

我在这里读到了几个关于这个主题的问题,这个问题似乎让我感到困惑。我刚刚开始学习C ++,我还没有学过模板或运算符重载等等。

现在有一种简单的方法来重载

class My {
public:
    int get(int);
    char get(int);
}

没有模板或奇怪的行为?或者我应该

class My {
public:
    int get_int(int);
    char get_char(int);
}

11 个答案:

答案 0 :(得分:89)

不,没有。您不能基于返回类型重载方法。

重载分辨率会考虑功能签名。函数签名由以下内容组成:

  • 功能名称
  • cv修饰符
  • 参数类型

这是引用:

1.3.11签名

  

有关参与重载的函数的信息   resolution(13.3):它的参数类型列表(8.3.5),如果是   function是一个类成员,函数上的cv-qualifiers(如果有的话)   本身和声明成员函数的类。 [...]

选项:

1)更改方法名称:

class My {
public:
    int getInt(int);
    char getChar(int);
};

2)输出参数:

class My {
public:
    void get(int, int&);
    void get(int, char&);
}

3)模板......在这种情况下过度杀伤。

答案 1 :(得分:73)

这是可能的,但我不确定这是我推荐的技术 初学者。与其他情况一样,当您想要选择功能时 取决于如何使用返回值,您使用代理;首先定义 像getChargetInt这样的函数,然后是通用的get() 像这样返回一个代理:

class Proxy
{
    My const* myOwner;
public:
    Proxy( My const* owner ) : myOwner( owner ) {}
    operator int() const
    {
        return myOwner->getInt();
    }
    operator char() const
    {
        return myOwner->getChar();
    }
};

根据需要将其扩展为多种类型。

答案 2 :(得分:8)

不,你不能通过返回类型重载;只能通过参数类型和const / volatile限定符。

一种替代方法是使用引用参数“返回”:

void get(int, int&);
void get(int, char&);

虽然我可能要么使用模板,要么使用不同命名的函数,例如你的第二个例子。

答案 3 :(得分:4)

你可以这样思考:

你有:

  int get(int);
  char get(int);

并且,在调用时不必强制收集函数的返回值。

现在,你调用

  get(10);  -> there is an ambiguity here which function to invoke. 

所以,如果基于返回类型允许重载,则没有意义。

答案 4 :(得分:4)

正在恢复旧线程,但是我看不到有人提到ref限定符超载。引用限定词是C ++ 11中添加的一种语言功能,我最近才偶然发现它-它没有像简历限定词。主要思想是区分两种情况:何时在右值对象上调用成员函数,以及何时在左值对象上调用成员函数。您基本上可以编写如下代码(我在稍微修改OP的代码):

#include <stdio.h>

class My {
public:
    int get(int) & { // notice &
        printf("returning int..\n");
        return 42;
    }
    char get(int) && { // notice &&
        printf("returning char..\n");
        return 'x';
    };
};

int main() {
    My oh_my;
    oh_my.get(13); // 'oh_my' is an lvalue
    My().get(13); // 'My()' is a temporary, i.e. an rvalue
}

此代码将产生以下输出:

returning int..
returning char..

当然,与cv-qualifiers一样,这两个函数都可能返回相同的类型,并且重载仍将成功。

答案 5 :(得分:4)

如前所述,模板在这种情况下是过大的,但是仍然值得一提。

class My {
public:
    template<typename T> T get(int);
};

template<> int My::get<int>(int);
template<> char My::get<char>(int);

答案 6 :(得分:2)

C ++中的返回类型无法重载。如果不使用模板,使用get_intget_char将是您可以做的最佳选择。

答案 7 :(得分:2)

您不能基于返回类型重载方法。最好的办法是创建两种语法略有不同的函数,例如在第二个代码片段中。

答案 8 :(得分:2)

虽然关于此问题的大多数其他评论在技术上都是正确的,但您可以有效重载返回值如果将其与重载输入参数结合使用。例如:

class My {
public:
    int  get(int);
    char get(unsigned int);
};

样本:

#include <stdio.h>

class My {
public:
    int  get(         int x) { return 'I';  };
    char get(unsinged int x) { return 'C';  };
};

int main() {

    int i;
    My test;

    printf( "%c\n", test.get(               i) );
    printf( "%c\n", test.get((unsigned int) i) );
}

由此产生的结果是:

I 
C

答案 9 :(得分:0)

您不能根据函数的返回类型重载函数。 您可以根据此函数所使用的参数的类型和数量进行操作。

答案 10 :(得分:0)

我通过代理使用了詹姆斯·坎泽的答案:

https://stackoverflow.com/a/9569120/262458

我想避免在void *上使用大量难看的static_cast,所以我这样做了:

#include <SDL_joystick.h>
#include <SDL_gamecontroller.h>

struct JoyDev {
    private:
        union {
            SDL_GameController* dev_gc = nullptr;
            SDL_Joystick*       dev_js;
        };
    public:
        operator SDL_GameController*&() { return dev_gc; }
        operator SDL_Joystick*&()       { return dev_js; }

        SDL_GameController*& operator=(SDL_GameController* p) { dev_gc = p; return dev_gc; }
        SDL_Joystick*&       operator=(SDL_Joystick* p)       { dev_js = p; return dev_js; }
};

struct JoyState {
    public:
        JoyDev dev;
};

int main(int argc, char** argv)
{
    JoyState js;

    js.dev = SDL_JoystickOpen(0);

    js.dev = SDL_GameControllerOpen(0);

    SDL_GameControllerRumble(js.dev, 0xFFFF, 0xFFFF, 300);

    return 0;
}

完美工作!