С vs С++
Правила форума
Пожалуйста, ознакомьтесь с правилами данного форума
Пожалуйста, ознакомьтесь с правилами данного форума
-
- Завсегдатай
- Сообщения: 251
- Зарегистрирован: 09 сен 2004, 23:58
С vs С++
Всегда думал, что С++ как минимум advanced C. Но жизнь иногда ставит в тупик. При попытке миграции с С на С++ возникла проблема, описанная ниже. Пару решений я нашел, но они кривоваты.
Специалисты по С++ подтягиваемся:
Проблема связана с сигнатурой функции greeting. Код приведенный ниже работает в С, но не в С++. Как его элегантно заставить работать в С++?
#include <stdio.h>
void use_int(int *);
void use_float(float *);
void greeting(void (*)(void *), void *);
int main(void) {
int i_age = 22;
float f_age = 22.0;
void *p;
p = &i_age;
greeting(use_int, p); //first call
p = &f_age;
greeting(use_float, p); //second call
//getchar();
return 0;
}
void greeting(void (*fp)(void *), void *q) {
fp(q);
}
void use_int(int *r) {
int a;
a = * (int *) r;
printf("As an integer, you are %d years old.\n", a);
}
void use_float(float *s) {
float *b;
b = (float *) s;
printf("As a float, you are %f years old.\n", *b);
}
Специалисты по С++ подтягиваемся:
Проблема связана с сигнатурой функции greeting. Код приведенный ниже работает в С, но не в С++. Как его элегантно заставить работать в С++?
#include <stdio.h>
void use_int(int *);
void use_float(float *);
void greeting(void (*)(void *), void *);
int main(void) {
int i_age = 22;
float f_age = 22.0;
void *p;
p = &i_age;
greeting(use_int, p); //first call
p = &f_age;
greeting(use_float, p); //second call
//getchar();
return 0;
}
void greeting(void (*fp)(void *), void *q) {
fp(q);
}
void use_int(int *r) {
int a;
a = * (int *) r;
printf("As an integer, you are %d years old.\n", a);
}
void use_float(float *s) {
float *b;
b = (float *) s;
printf("As a float, you are %f years old.\n", *b);
}
- ajkj3em
- Маньяк
- Сообщения: 2063
- Зарегистрирован: 12 ноя 2006, 06:53
Re: С vs С++
void use_int(void *r) {
int a;
a = * (int *) r;
printf("As an integer, you are %d years old.\n", a);
}
void use_float(void *s) {
float *b;
b = (float *) s;
printf("As a float, you are %f years old.\n", *b);
}
вто если дешево и сердито
* перевод с транслита
int a;
a = * (int *) r;
printf("As an integer, you are %d years old.\n", a);
}
void use_float(void *s) {
float *b;
b = (float *) s;
printf("As a float, you are %f years old.\n", *b);
}
вто если дешево и сердито
* перевод с транслита
- Azazello
- Житель
- Сообщения: 769
- Зарегистрирован: 16 янв 2007, 04:31
- sz
- Маньяк
- Сообщения: 1266
- Зарегистрирован: 17 фев 2003, 19:34
Re: С vs С++
На плюсах нынче кошернее писать:ajkj3em писал(а):void use_int(void *r) {
int a;
a = * (int *) r;
printf("As an integer, you are %d years old.\n", a);
}
void use_float(void *s) {
float *b;
b = (float *) s;
printf("As a float, you are %f years old.\n", *b);
}
вто если дешево и сердито
* перевод с транслита
a = * reinterpret_cast<int*>( r );
-
- Завсегдатай
- Сообщения: 251
- Зарегистрирован: 09 сен 2004, 23:58
Re: С vs С++
Я так и выкрутился. Однако при этом use_int() теряет строгое типизирование и может быть вызвана не с первоначально требуемым аргументом int* . В этом-то я и вижу кривизну, которой хотелось бы избежать.ajkj3em писал(а):void use_int(void *r) {
int a;
a = * (int *) r;
printf("As an integer, you are %d years old.\n", a);
}
void use_float(void *s) {
float *b;
b = (float *) s;
printf("As a float, you are %f years old.\n", *b);
}
вто если дешево и сердито
* перевод с транслита
- sz
- Маньяк
- Сообщения: 1266
- Зарегистрирован: 17 фев 2003, 19:34
- ajkj3em
- Маньяк
- Сообщения: 2063
- Зарегистрирован: 12 ноя 2006, 06:53
Re: С vs С++
строгое типизирование теряетcя при первом downcast'е в void.i_van писал(а):Я так и выкрутился. Однако при этом use_int() теряет строгое типизирование и может быть вызвана не с первоначально требуемым аргументом int* . В этом-то я и вижу кривизну, которой хотелось бы избежать.
в оригинальном коде ничего не мешает вызвать greeting(use_int, &f_age),
так шта кривизна там присутcтвует и без С++
- aissp
- Маньяк
- Сообщения: 2710
- Зарегистрирован: 07 ноя 2005, 09:51
- Azazello
- Житель
- Сообщения: 769
- Зарегистрирован: 16 янв 2007, 04:31
Ну, если templates использовать, то пожалуй так можно:
Код: Выделить всё
#include <iostream>
#include <typeinfo>
using namespace std;
template < typename TType > struct TypeTraits
{
};
struct TypeTraits< int >
{
static inline void SetPrecision( void )
{
cout << dec;
}
};
struct TypeTraits< float >
{
static inline void SetPrecision( void )
{
cout << fixed;
}
};
struct TypeTraits< double >
{
static inline void SetPrecision( void )
{
cout << scientific;
}
};
template < typename TType > void Greetings( TType fAge )
{
TypeTraits< TType > :: SetPrecision();
cout << "In "<< typeid( TType ).name() << "-type representation, your are " << fAge << " years old." << endl;
}
int main( void )
{
int lAgeI = 22;
float lAgeF = 22;
double lAgeD = 22;
Greetings( lAgeI );
Greetings( lAgeF );
Greetings( lAgeD );
cin.get();
return( 0 );
}
Program output писал(а): In int-type representation, you are 22 years old.
In float-type representation, you are 22.000000 years old.
In double-type representation, you are 2.200000e+01 years old.
- ajkj3em
- Маньяк
- Сообщения: 2063
- Зарегистрирован: 12 ноя 2006, 06:53
http://www.ariel.com.au/jokes/The_Evolu ... ammer.htmlAzazello писал(а):Ну, если templates использовать, то пожалуй так можно:
:-)
- aissp
- Маньяк
- Сообщения: 2710
- Зарегистрирован: 07 ноя 2005, 09:51
ну если мы все хором извращаемся то вынужден поправить код
name() соотвественно тоже должна обрабатываться в классе свойств. Смысл так делать много и никакого одновременно

Код: Выделить всё
template < typename TType, typename MyTraits = TypeTriats<TType> > void Greetings( TType fAge )
{
MyTraits :: SetPrecision();
cout << "In "<< MyTraits::name() << "-type representation, your are " << fAge << " years old." << endl;
}
- Azazello
- Житель
- Сообщения: 769
- Зарегистрирован: 16 янв 2007, 04:31
I like the Master Programmer version

С MyTraits согласен - это более "правильный" стиль (торопился, у меня проф. сидел на шееname() соотвественно тоже должна обрабатываться в классе свойств.

- aissp
- Маньяк
- Сообщения: 2710
- Зарегистрирован: 07 ноя 2005, 09:51
лучше на ты а то у меня шок культурный сразу 
Вобшем да ты прав, только уточню - трайтс класс уточнений, на етапе проихводства трайтса ты абсолютно точно знаешь тип вызова (для етого класс и служит не так ли?) поетому вызов typeId отпадает сам собой. Мне кажется не очень хороший стиль, когда по сути есть два различных места хранения инфо о типе. ДА и не верю я в корректную работу тайпАйдИ
(ето основная причина)

Вобшем да ты прав, только уточню - трайтс класс уточнений, на етапе проихводства трайтса ты абсолютно точно знаешь тип вызова (для етого класс и служит не так ли?) поетому вызов typeId отпадает сам собой. Мне кажется не очень хороший стиль, когда по сути есть два различных места хранения инфо о типе. ДА и не верю я в корректную работу тайпАйдИ

- Azazello
- Житель
- Сообщения: 769
- Зарегистрирован: 16 янв 2007, 04:31
Согласен - некрасиво дублировать. Просто, RTTI всё равно нужно для dynamic_cast и virtual destructor clean-up, а, значит, TypeInfo уже есть. aissp, то есть, Вы dynamic_cast совсем не пользуете (просто интересно, как люди пишутaissp писал(а):Мне кажется не очень хороший стиль, когда по сути есть два различных места хранения инфо о типе. ДА и не верю я в корректную работу тайпАйдИ(ето основная причина)

Да, простите за "Вы" - привычка

- aissp
- Маньяк
- Сообщения: 2710
- Зарегистрирован: 07 ноя 2005, 09:51
да за вы надо отучаться. А то представляешь типа Дорогой иван данилыч косячек то не отсасывайте и не мусольте, передавайте по кругу поджалста... 
там с темплатами по коду нигде никакой виртальности нету
точнее она есть но на етапе компиляции тока. А с динамиком - мне кажется единственное место где он применяется ето когда условия изменились настолько что надо передизайнить а на ето нету времени, либо код совсем чужой и никакими адаптерами не спасешься - действия должны происходить внутри кода.
ну например у тя есть список коров и свиней для скотобойни (их с ферм списывают на мфсозаготовки по старости) и все замечательно они у тебя живут под классом жЫвотное. Вдруг оказывается что что у свиней с украины бывает по три ноги и их надо обрабатывать особо. Хозяин библиотеки добавляет функцию bool is3LegExist() которую не вставляет в оьщий интерфейс. и тебе уже передизайнить нету времени - вот тут тебе приходится использовать динамик каст. Если такие запросы на количество заслуженных украниских свинок редки, ты забиваешь на все и делаешь нисъодящее приведение. Мне кажется так. Красивый пример никак в голову не лезет. сорри
с typeid ни разу в жизни не применял на практике. Надо бы поглядеть когда применяется, но сдается мне что цели отладки и такая же ситуации как применеие динамик каста, только еше более екзотичные.
Все сказанное мое сугубое имху

там с темплатами по коду нигде никакой виртальности нету

ну например у тя есть список коров и свиней для скотобойни (их с ферм списывают на мфсозаготовки по старости) и все замечательно они у тебя живут под классом жЫвотное. Вдруг оказывается что что у свиней с украины бывает по три ноги и их надо обрабатывать особо. Хозяин библиотеки добавляет функцию bool is3LegExist() которую не вставляет в оьщий интерфейс. и тебе уже передизайнить нету времени - вот тут тебе приходится использовать динамик каст. Если такие запросы на количество заслуженных украниских свинок редки, ты забиваешь на все и делаешь нисъодящее приведение. Мне кажется так. Красивый пример никак в голову не лезет. сорри
с typeid ни разу в жизни не применял на практике. Надо бы поглядеть когда применяется, но сдается мне что цели отладки и такая же ситуации как применеие динамик каста, только еше более екзотичные.
Все сказанное мое сугубое имху