c ++隐式转换规则

时间:2011-01-19 23:49:35

标签: c++ implicit-conversion

我试图了解常规或成员函数调用中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&)

由于

5 个答案:

答案 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 );
}