我在这里读了一些关于此主题的问题,这似乎令我感到困惑。我刚刚开始学习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);
}
?
int
返回值将是这样的(int)get(9)
,用char
这样的(char)get(9)
。
Answers:
不,没有。您不能基于返回类型重载方法。
重载解析考虑了功能签名。函数签名由以下内容组成:
这是报价:
1.3.11签名
有关参与重载解析的函数的信息(13.3):其参数类型列表(8.3.5),如果该函数是类成员,则该函数本身和该类上的cv限定词(如果有)在其中声明成员函数。[...]
选项:
1)更改方法名称:
class My {
public:
int getInt(int);
char getChar(int);
};
2)out参数:
class My {
public:
void get(int, int&);
void get(int, char&);
}
3)模板...在这种情况下过大了。
My::get<T>(int)
。这是一个有效的替代方法_if 1),您必须处理许多不同的类型,并且都使用相同的基本代码(例如boost::lexical_cast<T>( someStringValue )
,或者必须能够从其他模板调用这些函数(myMy.get<T>( i )
,这T
是另一个模板的参数) –否则,如Luchian所说,他们是过大杀手
my.get(0);
编译器,则将无法决定执行哪段代码。
void foo(int x = 0) {} void foo(double x = 0) {}
不应使用@benzado 。但是,事实并非如此。仅在编译器确实无法区分(foo()
)的情况下,您才会得到错误
有可能,但是我不确定这是我向初学者推荐的技术。与其他情况一样,当您希望函数的选择取决于返回值的使用方式时,可以使用代理。首先定义类似getChar
和的函数getInt
,然后定义一个泛型get()
,该泛型返回如下所示的Proxy:
class Proxy
{
My const* myOwner;
public:
Proxy( My const* owner ) : myOwner( owner ) {}
operator int() const
{
return myOwner->getInt();
}
operator char() const
{
return myOwner->getChar();
}
};
根据需要将其扩展为多种类型。
std::string
,而代理仅提供operator char const*()
,则它将无法正常工作。
不,您不能按返回类型重载;仅按参数类型和const / volatile限定符。
一种替代方法是使用引用参数“返回”:
void get(int, int&);
void get(int, char&);
尽管我可能会使用模板,也可能会使用名称不同的函数,例如您的第二个示例。
int
错误代码。
恢复旧线程,但我看不到有人提到ref限定符超载。引用限定词是C ++ 11中添加的一种语言功能,我最近才偶然发现它-它不像cv限定词那样广泛。主要思想是区分两种情况:何时在右值对象上调用成员函数,以及何时在左值对象上调用成员函数。您基本上可以编写如下代码(我在稍微修改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一样,这两个函数都可能返回相同的类型,并且重载仍将成功。
尽管有关此问题的大多数其他注释在技术上都是正确的,但如果将返回值与重载输入参数结合使用,则可以有效地重载返回值。例如:
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
在C ++中,无法通过返回类型来重载。如果不使用模板,则使用get_int
和get_char
将是您的最佳选择。
template <class T> T get(int)
行得通吗?
get<int>
或者get<char>
,它并没有真正得到你太多了get_int
和get_char
如果你不也用其他的模板功能。
T
您是否有类似的东西T get(T)
。如果您调用get('a')
,编译器将推导T
a,char
而不必显式调用get<char>('a')
。我仍然不确定这是否是标准的,尽管我认为是标准的。仅供参考,GCC和Clang都支持。
T
其他所有位置的值,包括返回类型。我希望您能T
在Niklas的第一句话中举例说明该函数的编译器。
我使用代理人使用James Kanze的答案:
https://stackoverflow.com/a/9569120/262458
我想避免在void *上使用大量难看的static_casts,所以我这样做:
#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;
}
完美的作品!