C++ Type Conversion | Implicit, Explicit, and User-Defined
이 글의 핵심
Type conversions in C++ include compiler promotions, C++-style casts, and user-defined conversions via constructors and conversion operators—controlled with explicit and static_cast.
Implicit conversions
The compiler applies standard conversions automatically when safe or allowed:
int x = 10;
double y = x; // int -> double
float f = 3.14f;
int z = f; // float -> int (truncates)
bool b = 42; // int -> bool (nonzero -> true)
Explicit casts
double d = 3.14;
int x = (int)d; // C-style
int y = static_cast<int>(d); // preferred in C++
Conversion constructors
class Distance {
double meters;
public:
Distance(double m) : meters(m) {}
double getMeters() const { return meters; }
};
void printDistance(Distance d) {
std::cout << d.getMeters() << "m\n";
}
int main() {
printDistance(100.5); // implicit double -> Distance
printDistance(Distance(50.0)); // explicit
}
explicit constructors
class Distance {
double meters;
public:
explicit Distance(double m) : meters(m) {}
double getMeters() const { return meters; }
};
void printDistance(Distance d) {}
int main() {
// printDistance(100.5); // error
printDistance(Distance(100.5)); // OK
}
Conversion operators
class Distance {
double meters;
public:
Distance(double m) : meters(m) {}
operator double() const { return meters; }
};
int main() {
Distance d(100.5);
double x = d; // implicit Distance -> double
}
Practical examples
String wrapper
class String {
std::string data;
public:
String(const char* str) : data(str) {}
explicit String(const std::string& str) : data(str) {}
operator std::string() const { return data; }
operator const char*() const { return data.c_str(); }
};
Smart pointer–style explicit operator bool
template<typename T>
class SmartPtr {
T* ptr;
public:
explicit SmartPtr(T* p = nullptr) : ptr(p) {}
~SmartPtr() { delete ptr; }
explicit operator bool() const { return ptr != nullptr; }
T& operator*() const { return *ptr; }
T* operator->() const { return ptr; }
};
Temperature types
Use explicit ctors and named conversions to avoid accidental unit mixing.
Fraction with explicit conversion operators
class Fraction {
int numerator, denominator;
public:
Fraction(int n, int d = 1) : numerator(n), denominator(d) {}
explicit operator double() const {
return static_cast<double>(numerator) / denominator;
}
};
int main() {
Fraction f(3, 4);
double d = static_cast<double>(f);
}
Standard conversion sequence (sketch)
Integer promotion, integral/floating conversions, pointer conversions, boolean conversion—see the standard for the full ordering.
User-defined conversion limits
class A { public: A(int) {} };
class B { public: B(const A&) {} };
int main() {
// B b = 42; // error: needs int->A and A->B (too many user conversions)
A a = 42;
B b = a;
}
At most one user-defined conversion in an implicit sequence (with exceptions for explicit paths).
Common problems
Accidental Array from size_t
Mark single-arg ctors explicit to avoid func(10) creating an Array unintentionally.
Implicit conversion operators
Prefer explicit operator T() when implicit conversion causes surprises.
explicit(bool) (C++20)
Conditional explicit on templates—for converting constructors that should only be implicit when safe.
FAQ
Q: When use explicit?
A: Single-argument ctors and conversion operators that should not participate in silent conversions.
Q: Conversion ctor vs conversion operator?
A: Ctor: other type → this type. Operator: this type → other type.
Q: C vs C++ casts?
A: Prefer static_cast, const_cast, reinterpret_cast, dynamic_cast—each shows intent.
Resources: Effective C++, C++ Primer, cppreference.
Related posts
- C++ explicit keyword
- C++ casting guide
- C++ Copy initialization
Keywords
C++, type conversion, implicit conversion, explicit, static_cast, conversion operator.
More links
- C++ Copy initialization