views:

188

answers:

3

I thought that constructors control initialization and operator= functions control assignment in C++. So why does this code work?

#include <iostream>
#include <cmath>
using namespace std;

class Deg {
    public:
        Deg() {}
        Deg(int a) : d(a) {}        
        void operator()(double a)
        {
            cout << pow(a,d) << endl;
        }

    private:
        int d;
};

int
main(int argc, char **argv) 
{
    Deg d = 2;
    d(5);
    d = 3; /* this shouldn't work, Deg doesn't have an operator= that takes an int */
    d(5);
    return 0;
}

On the third line of the main function, I am assigning an int to an object of class Deg. Since I don't have an operator=(int) function, I thought that this would certainly fail...but instead it calls the Deg(int a) constructor. So do constructors control assignment as well?

+14  A: 

This is what's called implicit type conversion. The compiler will look to see if there's a constructor to directly change from the type you're assigning to the type you're trying to assign, and call it. You can stop it from happening by adding the explicit keyword in front of the constructor you wouldn't like to be implicitly called, like this:

explicit Deg(int a) : d(a) {}

JonM
+1 for explicit
dimba
At least one company I've worked at has had the rule "use explicit on all constructors unless there's a good reason not to" among its coding standards. That helps avoid potentially puzzling situations like this.
Sean
I suppose you mean on all constructors that can be invoked with a single argument :) ?
Matthieu M.
"A good reason not to [use explicit]" would be needless confusion when used on multi-arg ctors.
MSalters
A: 

type casting tries to make a copy of the object int and calls constructor of Deg with an int ... yes?

n00b32
+2  A: 

Just to clarify JonM's answer:

For the line d = 3, an assignment operator is involved. 3 is being implicitly converted to a Deg, as JonM said, and then that Deg is assigned to d using the compiler-generated assignment operator (which by default does a member-wise assignment). If you want to prevent assignment, you must declare a private assignment operator (and do not implement it):

//...
private:
    Deg& operator=(const Deg&);
}