2015-03-10 2 views
0

Я попытался написать класс-оболочку для основных типов, но столкнулся с проблемой при использовании printf.C++ Type Wrapper printf печатает неправильное значение для float

По какой-то причине printf работает с int, но не с поплавком. std :: cout однако работает с обоими просто отлично.

printf работает правильно, конечно, когда я явно бросается в поплавок.

template <typename T> 
class Type 
{ 
public: 
    Type() : _mData() {} 
    Type(const T& _data) : _mData(_data) {} 

    operator T() const { return _mData; } 
    operator std::string() const { return std::to_string(_mData); } 

private: 
    T _mData; 
}; 

int main(void) 
{ 
    Type<int> someInt(200); 

    std::cout << "int" << std::endl; 
    std::cout << "std::cout: " << someInt <<std::endl; 
    printf("printf: %d\n\n", someInt); 


    Type<float> someFloat(300.3); 
    std::cout << "float" << std::endl; 
    std::cout << "std::cout: " << someFloat <<std::endl; 
    printf("printf: %f\n\n", someFloat); 

    return 0; 
} 

output: 
int 
std::cout: 200 
printf: 200 

float 
std::cout: 300.3 
printf: 0.000000 

Почему это работает с int?

Почему это не работает с поплавком?

Как я могу заставить его работать должным образом без явного литья?

+3

Причина, по которой она работает (или появляется) для int, по той же причине, что она не работает для float. В обоих случаях это неопределенное поведение. 'printf' не является безопасным для типов, а не расширяемым для обработки типов, не указанных в его спецификации. –

+0

И, в частности, ваши конверсии никогда не называются, поскольку для них нет причин, вы не передаете тип функции, ожидающей, скажем, 'float'. Таким образом, 'Type' передается, и он имеет представления' int' в нужном месте. На идеоне «float» тоже находится в правильном месте. В вашем компиляторе кажется, что что-то еще происходит. Но кто заботится, он сломан в любом случае, кажется, что работать хуже. – BoBTFish

+0

похоже похоже в этом случае. Возможно ли получить внутреннее представление байта моего класса? – Gamer2015

ответ

1

Почему это работает с int?

Это UB. На вашей конкретной машине это работает.

Почему это не работает с поплавком?

По той же причине, что и выше.

Как я могу заставить его работать должным образом без явного литья?

Неправильно, вы не можете. printf был создан для C, в то время, когда C++ не было (и ООП не рассматривался в дизайне printf). Из-за этого printf не может быть расширен для новых типов.

Вы можете создать функцию-обертку, которая выполняет преобразование типов, поддерживаемых printf (явно), и вызывает printf внутренне. Это громоздко, подвержено ошибкам и т. Д.

Это одно из основных преимуществ iostreams C++ для семейства функций [s | f] printf.

Смежные вопросы