I am trying to understand the rules of c++ automatic and explicit conversions in regular or member function calls. I wrote the following code and it fails compilatio开发者_如何学JAVAn:
#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;
}
However, can I conclude that the functions only expect the exact matching parameter? I remember reading that automatic conversions happen according to the conversion rules. Can some shed some light on the correct rules pls?
Here is the error:
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&)
Thanks
void getVal(int& a);
This function takes an int
by reference. You must pass it an int
. This is similar to how if you had a function
void getVal(int* a);
you would need to pass it a pointer to an int
(not a pointer to a short
or any other type).
One reason for this is that you are able to modify the int
from within the function. In order to allow you to pass an object of another type (e.g. a short
) to this function, a temporary object of type short
would have to be created at runtime and a reference to that temporary object would have to be passed.
This wouldn't be ideal because you might accidentally end up passing the wrong type of object (e.g. a short
) and expecting it to be modified by the function, when in fact a temporary copy of type int
would be modified by the function, not the original short
.
You are, however, permitted to bind const references to temporary objects, so if your function was declared as
void getVal(const int& a);
you would be able to pass it any type that is convertible to int
. This makes some sense, since the function cannot modify the referenced object (because it is a const reference), so the "oops, I'm accidentally modifying a temporary object" problem doesn't exist.
Conversions can also take place when you pass by value, but this too makes sense: when you pass by value, a copy has to be made anyway (the copy that is passed to the function by value), so the conversion can take place as part of that copy.
The problem is that if an implicit conversion is required, then a temporary variable is created. You cannot have a non-const reference to a temporary variable, so you would need to make your member function void getVal(const int &a)
or void getVal(int a)
.
Implicit conversion should be avoided. C++ is a strongly typed language it is far better to create functions for the types you wish to accept, use templates, or explicitly cast your type to another type, etc.
Constructor casting or using static_cast<>
, dynamic_cast<>
, or reinterpret_cast<>
are some of the options depending on the situation when you need to convert types from one to another.
Templates can allow you to handle multiple types a little easier.
template<typename T>
void getVal(const T& a)
{
// do something
}
Implicit conversions are done by creating an rvalue (temporary), and rvalues cannot be bound to non-const references. That is the reason why it is not working. If, on the other hand you change the signature to take the arguments either by value or by constant reference, then it will work:
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 );
}
Pass by reference means, creating an alias for the same type. So try changing void getVal(int& a)
to void getVal(int a)
, to work for the other function calls differing the passing parameter type
精彩评论