liveBook · Manning

Conversion constructor

As explained in 100 C++ Mistakes and How to Avoid Them

A constructor that can convert an argument of another type into an object of its class type, especially when it has one parameter.

A conversion constructor takes an argument of another type and builds an object of its class type. A one-parameter constructor can therefore let the compiler convert values silently, often when a function call or operator needs a different type. section 2.2 section 9.8

The hidden conversion cost

In a Complex class with Complex(double real, double imag = 0), expressions such as c1 + 3.14159 and 2.71828 + c1 silently construct temporary Complex objects. The four-line example performs six constructor calls; more complex types could also incur destructor calls. The code is correct, but the hidden work can make performance and maintenance harder to assess. section 9.8

Use explicit when callers should not receive uncontrolled implicit conversions: explicit Complex(double real, double imag = 0) still permits direct construction but prevents the compiler from using the constructor for automatic conversions. When mixed-type operations are intentional, provide overloaded operators for the supported types instead of relying on conversion. section 2.2 section 9.8

Listing 9.20 Implicit, silent, and expensive constructor type conversions
class Complex {
private:
    double real;
    double imag;
public:
    Complex(double real, double imag=0) : real(real), imag(imag) {}
    double getReal() const { return real; }
    double getImag() const { return imag; }
};
const Complex operator+(const Complex& lhs, const Complex& rhs) {
    return Complex(lhs.getReal()+rhs.getReal(), lhs.getImag()+rhs.getImag());
}
 
int main() {
    Complex c1(2.2);                                      #1
    Complex c2 = c1 + 3.14159;                            #2
    Complex c3 = 2.71828 + c1;                            #3
    Complex c4 = 2.71828 + 3.14159;                       #4
}

Inspect the Complex example to trace where implicit conversions create temporary objects. section 9.8

Listing 9.21 Minimizing constructor conversions by providing overloaded operators
class Complex {
private:
    double real;
    double imag;
public:
    Complex(double real, double imag=0) : real(real), imag(imag) {}
    double getReal() const { return real; }
    double getImag() const { return imag; }
};
const Complex operator+(const Complex& lhs, const Complex& rhs) {
    return Complex(lhs.getReal()+rhs.getReal(), lhs.getImag()+rhs.getImag());
}
const Complex operator+(const Complex& lhs, double rhs) {    #1
    return Complex(lhs.getReal()+rhs, lhs.getImag());
}
const Complex operator+(double lhs, const Complex& rhs) {    #2
    return Complex(lhs+rhs.getReal(), rhs.getImag());
}

int main() {
    Complex c1(2.2);
    Complex c2 = c1 + 3.14159;
    Complex c3 = 2.71828 + c1;
    Complex c4 = 2.71828 + 3.14159;
}

Compare overloads accepting double values directly, reducing conversions while preserving the intended arithmetic expressions. section 9.8

How 100 C++ Mistakes and How to Avoid Them covers it

How deep it goes
Explains conversion selection, temporary construction, destructor cost, and explicit or overload-based remedies.
Examples
Uses Circle construction and Complex arithmetic to show conversion behavior, hidden calls, and direct operator overloads.
What you can do after
Apply it by marking constructors explicit or adding targeted overloaded operators for intentional mixed-type operations.
How it connects
Connects constructors with implicit conversions, overloaded operators, temporary objects, destructors, and return value optimization.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of 100 C++ Mistakes and How to Avoid Them. The section links point to the parts of the book it draws on.