Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > перегрузка функций и приведение типов


Автор: GrafF812 31.8.2010, 10:55
Привет, есть такой вызов функции square()
Код


 // int square(int x) {return x * x;}
double square(double y) {return y * y;}

int main()
{
    setlocale(LC_CTYPE, "Russian_Russia.1251");
    
    cout << "Квадрат целого числа 7 равен "
        << square(7) << endl
        << "Квадрат числа 7.5 типа double равен "
        <<square(7.5) << endl;
    
    return 0;
}

Подскажите почему при вызове функции square(7), вызывается версия square(double) а не генерируется сообщение об ошибки?

Автор: djamshud 31.8.2010, 11:09
Потому что int преобразуется в double.

Автор: GrafF812 31.8.2010, 11:35
djamshud, в чем тогда смысл перегрузки функций ?, если все равно происходит неявное преобразование типов, как в этом случае.

Автор: djamshud 31.8.2010, 11:40
В том, чтобы можно было сделать так:

Код

struct point{
double x,y;};

void foo(double x,double y){
...
}

void foo(struct point const &point){
...
}


В вашем случае вы можете указать разную логику для работы над int и над double, т.к. преобразование типов включается после того, как не нашлось прямого действия.

Добавлено через 5 минут и 42 секунды
ну или вот пример из моей недавней практики:

Код

void foo(char const *str){
...
}

void foo(void const *ptr){
...
}


Одна логика для работы со строкой и совершенно другая - для любых других указателей.

Автор: ИванМ 31.8.2010, 15:52
Цитата(GrafF812 @  31.8.2010,  11:35 Найти цитируемый пост)
в чем тогда смысл перегрузки функций

В вашем коде никакой перегрузки функций и нет. Если раскомментировать первую строчку, то как раз перегрузка произойдет. Неявное преобразование типа происходит, только если нет перегрузки.

Автор: mes 31.8.2010, 18:14
Цитата(ИванМ @  31.8.2010,  14:52 Найти цитируемый пост)
 Неявное преобразование типа происходит, только если нет перегрузки.

звучит резковато  smile  

Автор: ИванМ 31.8.2010, 20:29
mes, я вообще очень суров smile 

Автор: Леопольд 31.8.2010, 20:45
Цитата(ИванМ @  31.8.2010,  15:52 Найти цитируемый пост)
Неявное преобразование типа
Здесь имеет место так называемое продвижение. int неявно преобразуется к double, но не наоборот.
Когда вызывается функция, происходит поиск её имени. Здесь нет ползовательских (user-defined) типов (проще говоря, классов или енумов), поэтому ADL не выполняется. Выбирается та функция, которая подходит лучше всего, т.е. та, для вызова которой надо сделать как можно меншьше допустимых приведений. 

Если в этой цепочке присутствуют приведения типа определённые пользователем, (не explicit конструкторы классов или всевозможные operator T()), то допускается не более одного.
Код
#include <iostream>

struct One{
};

struct Two{
   Two() {}
   Two(One) {}
   operator double() { return 0; }
};

void foo(double){
   std::cout<<"foo"<<std::endl;
}

int main(){
   One one;
   Two two;

   //foo(one); // error: cannot convert 'One' to 'double' for argument '1' to 'void foo(double)'
   foo(static_cast<Two>(one)); // делаем каст вручную
   foo(two);
   return 0;
}
http://codepad.org/WR1vT23v

Автор: ИванМ 31.8.2010, 20:57
Цитата(Леопольд @  31.8.2010,  20:45 Найти цитируемый пост)
int неявно преобразуется к double, но не наоборот.

Вот в этом месте не понятно. Вы имеете ввиду конкретный случай или вообще.

Автор: Леопольд 31.8.2010, 20:57
http://codepad.org/TgHD3o6O
Код
#include <iostream>

struct One{
};

struct Two{
   Two() {}
   Two(One) {}
   operator double() { return 0; }
};

void foo(double){
   std::cout<<"foo(double)"<<std::endl;
}

void bar();

int main(){
   One one;
   Two two;

   //foo(one); // error: cannot convert 'One' to 'double' for argument '1' to 'void foo(double)'
   foo(static_cast<Two>(one));
   foo(two);

   bar();

   return 0;
}

void foo(Two){
   std::cout<<"foo(Two)"<<std::endl;
}

void bar(){
   One one;
   Two two;
   foo(one);
   foo(two);
}


Добавлено @ 20:59
Цитата(ИванМ @  31.8.2010,  20:57 Найти цитируемый пост)
Вы имеете ввиду конкретный случай или вообще. 
Здесь речь про "продвижение" встроенных типов, оно идёт в одном напрвалении: char -> short -> int -> long -> float -> double . Здесь я "опустил" unsigned типы.

Автор: mes 1.9.2010, 00:13
Цитата(Леопольд @  31.8.2010,  19:57 Найти цитируемый пост)
оно идёт в одном напрвалении: char -> short -> int -> long -> float -> double 

все в одну бочку ?!  smile 

Автор: Леопольд 1.9.2010, 08:43
Цитата(mes @  1.9.2010,  00:13 Найти цитируемый пост)
все в одну бочку ?!
Я точно уже не помню. Лазить выскивать точную инфу нет времени...

Автор: baldina 1.9.2010, 09:23
в С++ компилятор осуществляет неявное (implicit) преобразование типов во время разбора выражений. эта некоторая слабость типизации есть дань совместимости с С и для опытных программистов довольно удобна, хотя иногда приводит к трудноуловимым ошибкам.
Правила преобразования (почти всегда) интуитивно понятны, хотя и не настолько просты, что бы выразить их одной строчкой.
Для избежания неявного преобразования есть два механизма - явное приведение типов _cast, (type), type() и ключевое слово explicit, применимое, к сожалению, лишь в конструкторах. Замечу, что первое - явное преобразование - не защищает от неявного:
Код

void foo (double);
foo ((int)5.5); // 5.5 -> int - > double -> 5.0

используя перегрузку функций можно специализировать функцию для определенного типа http://codepad.org/jJ7DkWBy, компилятор будет применять функцию, наиболее близкую по типу параметров, однако неявное преобразование это не отменяет

Автор: ИванМ 1.9.2010, 13:29
Леопольд, а как называется неявное преобразование double к int?

Автор: mes 1.9.2010, 14:07
Цитата(Леопольд @  1.9.2010,  07:43 Найти цитируемый пост)
Я точно уже не помню. 

тогда поправлю: 
Цитата(Леопольд @  31.8.2010,  19:45 Найти цитируемый пост)
Здесь имеет место так называемое продвижение. int неявно преобразуется к double, но не наоборот.

тут нет никакого продвижения smile

Цитата(ИванМ @  1.9.2010,  12:29 Найти цитируемый пост)
как называется неявное преобразование double к int? 

Floating-integral conversions

Цитата

4.9 Floating-integral conversions 
1 An rvalue of a floating point type can be converted to an rvalue of an integer type. The conversion truncates;
that is, the fractional part is discarded. The behavior is undefined if the truncated value cannot be
represented in the destination type. [Note: If the destination type is bool, see 4.12. ]
2 An rvalue of an integer type or of an enumeration type can be converted to an rvalue of a floating point
type. The result is exact if possible. Otherwise, it is an implementation-defined choice of either the next
lower or higher representable value. [Note: loss of precision occurs if the integral value cannot be represented
exactly as a value of the floating type. ] If the source type is bool, the value false is converted to
zero and the value true is converted to one.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)