2011-01-19 3 views
1

Я пытаюсь понять правила автоматических и явных преобразований C++ при регулярных вызовах функций или членов. Я написал следующий код и он не компиляции: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&) 

Благодаря

ответ

3
void getVal(int& a); 

Эта функция принимает intпо ссылке. Вы должны передать ему int. Это подобно тому, как если бы вы имели функцию

void getVal(int* a); 

вам нужно будет передать ему указатель на int (не указатель на short или любой другой тип).

Одна из причин этого заключается в том, что вы можете вносить изменения в функцию int. Чтобы позволить вам передать объект с другим типом (например, short) этой функции, временный объект типа short должен быть создан во время выполнения, и ссылка на этот временный объект должна быть передана.

Это не будет идеальным, потому что вы можете случайно передать неправильный тип объекта (например, short) и ожидать, что он будет изменен функцией, если на самом деле временная копия типа int будет изменена функция, а не оригинал short.

Вы, однако, разрешается связывать константные ссылки на временные объекты, поэтому, если ваша функция была объявлена ​​как

void getVal(const int& a); 

вы могли бы передать его любой тип, который конвертируется в int. Это имеет смысл, так как функция не может изменить ссылочный объект (потому что это ссылка на const), поэтому проблема «oops, I'm anime changeing the object object» не существует.

Конверсии могут также иметь место при передаче по значению, но это тоже имеет смысл: при передаче по значению копия должна быть сделана в любом случае (копия, передаваемая функции по значению), поэтому преобразование может состояться как часть этой копии.

+0

Спасибо за подробное объяснение Джеймс. – Kiran

0

Pass справочных средств, создание псевдонима для того же типа. Поэтому попробуйте изменить void getVal(int& a) на void getVal(int a), чтобы работать для других вызовов функций, отличающихся прохождением параметра параметра

2

Проблема в том, что если требуется неявное преобразование, создается временная переменная. Вы не можете ссылаться на неконстантную ссылку на временную переменную, поэтому вам нужно будет сделать свою функцию-член void getVal(const int &a) или void getVal(int a).

0

Неявные преобразования выполняются путем создания rvalue (временного), а rvalues ​​не могут быть привязаны к неконстантным ссылкам. Именно по этой причине он не работает.Если, с другой стороны, изменить подпись принять аргументы либо по значению или по постоянной ссылке, то он будет работать:

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); 
} 
2

неявное преобразование следует избегать. C++ является строго типизированным языком, гораздо лучше создавать функции для типов, которые вы хотите принять, шаблоны использования, или явно привести тип к другому типу и т.д.

литье Constructor или с помощью static_cast<>, dynamic_cast<> или reinterpret_cast<> являются некоторые из параметров зависят от ситуации, когда вам нужно преобразовывать типы из одного в другое.

Шаблоны могут позволить вам обрабатывать несколько типов немного проще.

template<typename T> 
void getVal(const T& a) 
{ 
    // do something 
} 
Смежные вопросы