C++98corebeginner
Conversion Functions
C++98 · The Foundation · Compiler flag: -std=c++98
Explanation
Member functions that define implicit or explicit conversions from a class type to another type.
Real-World Scenario
A `Fraction` class that converts to `double` for use in floating-point calculations.
Quick Snippet
snippet.cpp
class Fraction { public: operator double() const { return 0.5; } };Full Example
conversion_functions.cpp
// CodeNebula - C++98 Example: Conversion Functions
// Compile: g++ -std=c++98 -Wall -Wextra -o example conversion_functions.cpp
//
// This example demonstrates:
// - User-defined conversion operators: operator double(), operator int()
// - Simulating operator bool() safely in C++98 (the "safe bool" idiom)
// - Converting constructors (implicit type conversion via single-arg ctor)
// - Controlling implicit conversions
//
// NOTE: C++98 does not have the 'explicit' keyword for conversion operators.
// 'explicit' on constructors IS available in C++98 to prevent implicit
// converting construction.
#include <iostream>
// ============================================================
// 1. Temperature class with operator double()
// ============================================================
class Temperature {
private:
double celsius;
public:
Temperature(double c) : celsius(c) {
// This is a "converting constructor": allows double -> Temperature
}
// Conversion operator: Temperature -> double
// Allows Temperature objects to be used where a double is expected
operator double() const {
std::cout << " (operator double() called)" << std::endl;
return celsius;
}
double getFahrenheit() const {
return celsius * 9.0 / 5.0 + 32.0;
}
void print() const {
std::cout << " " << celsius << " C ("
<< getFahrenheit() << " F)" << std::endl;
}
};
// ============================================================
// 2. Fraction class with operator double() and operator int()
// ============================================================
class Fraction {
private:
int numerator;
int denominator;
public:
Fraction(int n, int d) : numerator(n), denominator(d) {
if (denominator == 0) {
std::cout << " WARNING: zero denominator, setting to 1" << std::endl;
denominator = 1;
}
}
// Convert to double (floating-point division)
operator double() const {
return static_cast<double>(numerator) / denominator;
}
// Convert to int (integer division, truncates)
operator int() const {
return numerator / denominator;
}
void print() const {
std::cout << " " << numerator << "/" << denominator << std::endl;
}
};
// ============================================================
// 3. SafeFlag: simulating "operator bool()" in C++98
//
// In C++98, a plain "operator bool()" is dangerous because bool
// implicitly converts to int, allowing nonsense like:
// SafeFlag f; int x = f + 3; // compiles but is meaningless
//
// The "safe bool" idiom uses a pointer-to-member instead.
// ============================================================
class SafeFlag {
private:
bool value;
// Private type used only for the safe bool conversion
typedef void (SafeFlag::*BoolType)() const;
void safeTrue() const {} // unused, exists only for its address
public:
SafeFlag(bool v) : value(v) {}
// Safe bool idiom: returns a non-NULL pointer-to-member if true,
// NULL if false. Works in if(), while(), &&, ||, but NOT in
// arithmetic expressions.
operator BoolType() const {
return value ? &SafeFlag::safeTrue : 0;
}
};
// ============================================================
// 4. Distance: explicit constructor to prevent implicit conversion
// ============================================================
class Distance {
private:
double meters;
public:
// 'explicit' prevents: Distance d = 5.0; (must write Distance d(5.0); )
explicit Distance(double m) : meters(m) {}
operator double() const { return meters; }
void print() const {
std::cout << " " << meters << " meters" << std::endl;
}
};
// A function that takes a double -- demonstrates implicit conversion
void showValue(double v) {
std::cout << " showValue received: " << v << std::endl;
}
int main() {
std::cout << "========================================" << std::endl;
std::cout << "1. operator double() -- Temperature" << std::endl;
std::cout << "========================================" << std::endl;
{
Temperature t(100.0);
t.print();
// Implicit conversion to double via operator double()
std::cout << "\n Using Temperature where double is expected:" << std::endl;
double d = t; // calls operator double()
std::cout << " d = " << d << std::endl;
std::cout << "\n Passing Temperature to showValue(double):" << std::endl;
showValue(t); // implicit conversion
std::cout << "\n Arithmetic with Temperature:" << std::endl;
double sum = t + 50.0; // Temperature -> double, then + 50.0
std::cout << " t + 50.0 = " << sum << std::endl;
}
std::cout << "\n========================================" << std::endl;
std::cout << "2. operator double() and operator int() -- Fraction" << std::endl;
std::cout << "========================================" << std::endl;
{
Fraction f(7, 2);
f.print();
double asDouble = static_cast<double>(f); // explicit cast to pick double
int asInt = static_cast<int>(f); // explicit cast to pick int
std::cout << " As double: " << asDouble << std::endl;
std::cout << " As int: " << asInt << std::endl;
}
std::cout << "\n========================================" << std::endl;
std::cout << "3. SAFE BOOL IDIOM" << std::endl;
std::cout << "========================================" << std::endl;
{
SafeFlag on(true);
SafeFlag off(false);
// Works in boolean contexts:
if (on) std::cout << " on is truthy" << std::endl;
if (!off) std::cout << " off is falsy" << std::endl;
// The following would NOT compile (safe bool prevents misuse):
// int x = on + 3; // ERROR: no matching operator+
// int y = on; // ERROR: cannot convert to int
std::cout << " (int x = on + 3; would NOT compile -- safe!)" << std::endl;
}
std::cout << "\n========================================" << std::endl;
std::cout << "4. EXPLICIT CONSTRUCTOR" << std::endl;
std::cout << "========================================" << std::endl;
{
// Distance d = 5.0; // Would NOT compile: explicit ctor
Distance d(5.0); // OK: direct initialisation
d.print();
// But operator double() still allows implicit conversion OUT:
double val = d;
std::cout << " Converted to double: " << val << std::endl;
// Converting constructor example (Temperature allows implicit):
Temperature t2 = 36.6; // implicit: double -> Temperature via ctor
std::cout << " Implicit ctor (Temperature t2 = 36.6):" << std::endl;
t2.print();
}
std::cout << "\n========================================" << std::endl;
std::cout << "5. SUMMARY" << std::endl;
std::cout << "========================================" << std::endl;
std::cout << " - operator T() lets a class convert to type T" << std::endl;
std::cout << " - Converting constructors let type T convert TO the class" << std::endl;
std::cout << " - Use 'explicit' on constructors to prevent surprise conversions" << std::endl;
std::cout << " - In C++98, use the safe-bool idiom instead of operator bool()" << std::endl;
return 0;
}
// Expected output:
// ========================================
// 1. operator double() -- Temperature
// ========================================
// 100 C (212 F)
//
// Using Temperature where double is expected:
// (operator double() called)
// d = 100
//
// Passing Temperature to showValue(double):
// (operator double() called)
// showValue received: 100
//
// Arithmetic with Temperature:
// (operator double() called)
// t + 50.0 = 150
//
// ========================================
// 2. operator double() and operator int() -- Fraction
// ========================================
// 7/2
// As double: 3.5
// As int: 3
//
// ========================================
// 3. SAFE BOOL IDIOM
// ========================================
// on is truthy
// off is falsy
// (int x = on + 3; would NOT compile -- safe!)
//
// ========================================
// 4. EXPLICIT CONSTRUCTOR
// ========================================
// 5 meters
// (operator double() called)
// Converted to double: 5
// Implicit ctor (Temperature t2 = 36.6):
// 36.6 C (97.88 F)
//
// ========================================
// 5. SUMMARY
// ========================================
// ...summary text...
Run command
g++ -std=c++98 -Wall -Wextra -o example conversion_functions.cpp