C++ 按返回类型重载

C++ 按返回类型重载,c++,overloading,C++,Overloading,我在这里读到了一些关于这个话题的问题,这些问题让我感到困惑。我刚开始学习C++,还没有研究过模板或者操作符重载等等。 现在有没有一种简单的过载方法 class My { public: int get(int); char get(int); } 没有模板或奇怪的行为?还是我应该 class My { public: int get_int(int); char get_char(int); } 不,没有。不能基于返回类型重载方法 重载解析将考虑函数签名。函数

我在这里读到了一些关于这个话题的问题,这些问题让我感到困惑。我刚开始学习C++,还没有研究过模板或者操作符重载等等。 现在有没有一种简单的过载方法

class My {
public:
    int get(int);
    char get(int);
}
没有模板或奇怪的行为?还是我应该

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

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

重载解析将考虑函数签名。函数签名由以下部分组成:

  • 函数名
  • cv限定符
  • 参数类型
以下是引述:

1.3.11签名

有关参与重载的函数的信息 分辨率(13.3):其参数类型列表(8.3.5),如果 函数是类成员,函数上的cv限定符(如果有) 本身和声明成员函数的类。[……]

选项:

1) 更改方法名称:

class My {
public:
    int getInt(int);
    char getChar(int);
};
2) 输出参数:

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

3) 模板。。。在这种情况下,过度使用。

在C++中,没有返回超载类型的方法。如果不使用模板,使用
get\u int
get\u char
将是最好的选择。

不,不能按返回类型重载;仅按参数类型和常量/易失性限定符

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

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

尽管我可能会使用一个模板,或者像您的第二个示例那样使用不同名称的函数。

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

不能根据函数的返回类型重载函数。
您可以根据此函数所采用的参数类型和数量来进行覆盖。

这是可能的,但我不确定这是否是我推荐的技术 初学者。与其他情况一样,当您希望函数的选择 根据返回值的使用方式,可以使用代理;首先定义 函数如
getChar
getInt
,然后是一个通用的
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();
    }
};

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

您可以这样想:

你有:

  int get(int);
  char get(int);
并且,在调用时收集函数的返回值不是强制性的

现在,你调用

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

因此,如果基于返回类型允许重载,则没有任何意义。

虽然关于此问题的大多数其他注释在技术上是正确的,但是如果将返回值与重载输入参数相结合,则可以有效地重载返回值。例如:

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


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


当然,与cv限定符一样,这两个函数可能返回相同的类型,重载仍然会成功。

我使用了James Kanze使用代理的答案:

我想避免在空白*上使用大量丑陋的静态_投射,所以我这样做了:

#包括
#包括
结构JoyDev{
私人:
联合{
SDL_GameController*dev_gc=nullptr;
SDL_操纵杆*dev_js;
};
公众:
运算符SDL_GameController*&(){return dev_gc;}
运算符SDL_*&(){return dev_js;}
SDL_GameController*&操作符=(SDL_GameController*p){dev_gc=p;返回dev_gc;}
SDL_操纵杆*&运算符=(SDL_操纵杆*p){dev_js=p;返回dev_js;}
};
结构状态{
公众:
乔伊德夫;
};
int main(int argc,字符**argv)
{
JoyState js;
js.dev=SDL_JoystickOpen(0);
js.dev=SDL_游戏控制器打开(0);
SDL_GameControllerRumble(js.dev,0xFFFF,0xFFFF,300);
返回0;
}

很好用

如前所述,在这种情况下,模板是多余的,但它仍然是一个值得一提的选项

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

template<> int My::get<int>(int);
template<> char My::get<char>(int);
我的班级{
公众:
模板T-get(int);
};
模板int My::get(int);
模板char My::get(int);

只是为了确定:像
模板T get(int)
这样的东西会起作用吗?是的,@Niklas,但如果你不使用其他模板功能,你必须称之为
get
get
,这对你来说并没有多大好处。@Rob:,如果您有类似于
T get(T)
的内容,编译器可以确定
T
。如果调用
get('a')
,编译器会推断
T
char
,您不必显式调用
get('a')
。我仍然不确定这是否是标准,尽管我认为是。仅供参考,GCC和Clang都支持这一点。这是非常标准的,@Netcoder,但这并不是编译器仅推导返回类型的情况,您认为这是可能的。在您的示例中,编译器推断出参数类型,一旦知道,它就会在其他任何地方填充
T
的值,包括返回类型。我希望您在Niklas的第一条注释中给出一个编译器为函数推导
T
的示例。您不能在返回类型上重载普通函数,但编译器将根据结果类型在转换运算符之间进行选择;您可以利用这一点来创建一个代理,该代理有效地充当返回类型重载的角色。@JeffPigarelli模板解决方案意味着成员模板:
My::get(int)
。这是一个有效的选择,如果1)你必须处理很多不同的类型,都是w
I 
C
#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..
class My {
public:
    template<typename T> T get(int);
};

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