我试图了解常规或成员函数调用中c ++自动和显式转换的规则。我编写了以下代码,但编译失败:
#include <iostream>
#include <string>
using namespace std;
class testExplicit {
public:
int intval;
short shortval;
double doubleval;
char charval;
string strval;
testExplicit(int a1, short a2, double a3, char a4, string& a5):
intval(a1),shortval(a2),doubleval(a3),charval(a4),strval(a5){}
void getVal(int& a) { a = intval; cout << "IntVal\n"; }
// void getVal(short& a) { a = shortval; cout << "Short Val\n"; }
// void getVal(double& a) { a = doubleval; cout << "Double Val\n"; }
// void getVal(char& a) { a = charval; cout << "Char Val\n"; }
// void getVal(string& a) { a = strval; cout << "String Val\n"; }
};
int main( int argc, char **argv ) {
string s ("test Str");
testExplicit test (100,10,10.05,5,s);
int i;
char c;
double d;
short f;
test.getVal(i);
test.getVal(c);
test.getVal(d);
test.getVal(f);
return 0;
}
但是,我可以得出结论,这些函数只需要精确的匹配参数吗?我记得读过自动转换是根据转换规则发生的。有些人可以对正确的规则有所了解吗?
这是错误:
test.cpp: In function 'int main(int, char**)':
test.cpp:38: error: no matching function for call to 'testExplicit::getVal(char&)'
test.cpp:17: note: candidates are: void testExplicit::getVal(int&)
test.cpp:39: error: no matching function for call to 'testExplicit::getVal(double&)'
test.cpp:17: note: candidates are: void testExplicit::getVal(int&)
test.cpp:40: error: no matching function for call to 'testExplicit::getVal(short int&)'
test.cpp:17: note: candidates are: void testExplicit::getVal(int&)
由于
答案 0 :(得分:4)
void getVal(int& a);
此功能通过引用获取int
。你必须传递int
。这类似于如果你有一个功能
void getVal(int* a);
你需要传递一个指向int
的指针(不是指向short
或任何其他类型的指针)。
这样做的一个原因是您可以从函数中修改int
。为了允许您将另一种类型的对象(例如short
)传递给此函数,必须在运行时创建类型为short
的临时对象,并且对该临时对象的引用将必须通过。
这可能不太理想,因为你可能不小心最终传递了错误类型的对象(例如short
)并期望它被函数修改,而实际上是类型{{的临时副本1}}将由函数修改,而不是原始int
。
但是,您可以将const引用绑定到临时对象,因此如果您的函数声明为
short
您可以将任何可转换为void getVal(const int& a);
的类型传递给它。这是有道理的,因为函数不能修改引用的对象(因为它是一个const引用),所以“oops,我不小心修改了一个临时对象”问题不存在。
当您按值传递时也可以进行转换,但这也是有意义的:当您按值传递时,无论如何都必须复制(通过值传递给函数的副本),因此转换可以作为该副本的一部分发生。
答案 1 :(得分:2)
问题是如果需要隐式转换,则会创建一个临时变量。您不能对临时变量进行非const引用,因此您需要使您的成员函数void getVal(const int &a)
或void getVal(int a)
。
答案 2 :(得分:2)
应避免隐式转换。 C ++是一种强类型语言,为您希望接受的类型创建函数,使用模板或将您的类型显式转换为其他类型等更好。
构造函数转换或使用static_cast<>
,dynamic_cast<>
或reinterpret_cast<>
是一些选项,具体取决于您需要将类型从一个转换为另一个时的情况。
模板可以让您更轻松地处理多种类型。
template<typename T>
void getVal(const T& a)
{
// do something
}
答案 3 :(得分:0)
通过引用传递意味着,为同一类型创建别名。因此,请尝试将void getVal(int& a)
更改为void getVal(int a)
,以便为不同的传递参数类型的其他函数调用工作
答案 4 :(得分:0)
通过创建rvalue(临时)来完成隐式转换,并且rvalues不能绑定到非const引用。这就是它无法正常工作的原因。另一方面,如果您更改签名以通过值或常量引用获取参数,那么它将起作用:
void f( int a ) { std::cout << a << std::endl; }
void g( const int& b ) { std::cout << b << std::endl; }
int main() {
char c = 'a'; // note that this the ASCII value of 'a'
f( c );
g( c );
short s = 4;
f( s );
g( s );
}