我在stackoverflow上看了一些关于这个主题的问题,但这似乎仍然困惑我。我刚开始学习C++,还没有学习模板或运算符重载等内容。
现在有没有简单的方法来进行重载?
class My {
public:
int get(int);
char get(int);
}
没有使用模板或奇怪的行为?还是我只需要
class My {
public:
int get_int(int);
char get_char(int);
}
我在stackoverflow上看了一些关于这个主题的问题,但这似乎仍然困惑我。我刚开始学习C++,还没有学习模板或运算符重载等内容。
现在有没有简单的方法来进行重载?
class My {
public:
int get(int);
char get(int);
}
没有使用模板或奇怪的行为?还是我只需要
class My {
public:
int get_int(int);
char get_char(int);
}
class My {
public:
int getInt(int);
char getChar(int);
};
2) 输出参数:
class My {
public:
void get(int, int&);
void get(int, char&);
}
3) 在这种情况下,使用模板可能过于复杂。
My::get<T>(int)
。如果满足以下条件,它是一个有效的选择:1)你需要处理许多不同类型的情况,但基本代码相同(例如 boost::lexical_cast<T>( someStringValue )
),或者你需要能够从其他模板中调用这些函数(myMy.get<T>( i )
,其中 T
是另一个模板的参数)。否则,正如Luchian所说,它们就是过度设计。 - James Kanzemy.get(0)
,编译器将无法决定执行哪一段代码。 - benzadovoid foo(int x = 0) {}
和 void foo(double x = 0) {}
应该被禁止。然而,实际上它们并没有被禁止。只有当编译器无法区分时(foo()
),你才会收到错误提示。 - 463035818_is_not_a_number这是可能的,但我不确定这是否是一种适合初学者的技术。像其他情况一样,当您想要函数的选择取决于返回值的使用方式时,可以使用代理; 首先定义像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();
}
};
将其扩展到您需要的任意类型。
std::string
,而代理只提供了 operator char const*()
,那么将无法工作。 - James Kanze如前所述,在这种情况下,模板可能有些过于复杂,但它仍然是值得一提的选项。
class My {
public:
template<typename T> T get(int);
};
template<> int My::get<int>(int);
template<> char My::get<char>(int);
void get(int, int&);
void get(int, char&);
尽管我可能会使用模板或者像你第二个示例中使用不同名称的函数。
一台计算机
int get(int);
char get(int);
而且,在调用函数时,收集返回值并非强制要求。
现在,你调用
get(10); -> there is an ambiguity here which function to invoke.
重新启动一个旧主题,但我发现没有人提到引用限定符的重载。引用限定符是C++11中添加的一种语言特性,我最近才发现它 - 它不像例如cv-限定符那样广泛。其主要思想是区分两种情况:当成员函数在rvalue对象上调用时和在lvalue对象上调用时。你基本上可以编写类似这样的代码(我稍微修改了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..
this&
vs this&&
)上进行常规函数重载。 - studgeek虽然其他评论在技术上都是正确的,但如果您将返回值重载与输入参数重载相结合,您可以有效地重载它。例如:
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)
这样的写法可行吗? - Niklas B.get<int>
或get<char>
,如果你没有使用其他模板特性,这并不比get_int
和get_char
更有优势。 - Rob KennedyT get(T)
的东西,编译器可以确定T
。如果你调用get('a')
,编译器推断出T
是一个char
,你不必显式地调用get<char>('a')
。我仍然不确定这是否是标准,尽管我认为它是。FYI,GCC和Clang都支持这个。 - netcoderT
的值,包括返回类型。我期望你能给出一个编译器推断Niklas第一条评论中函数的T
的例子。 - Rob Kennedy你不能根据返回类型重载方法。最好的方法是创建两个具有略微不同语法的函数,就像你第二段代码片段中那样。
我使用了James Kanze的答案,使用了代理:
https://dev59.com/SWkw5IYBdhLWcg3w6Oty#9569120
我想避免在 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;
}
运行完美!
int
返回值的实例将如下所示:(int)get(9)
,而使用char
的实例将如下所示:(char)get(9)
。 - AnArrayOfFunctions