Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Order of casting in C++

Tags:

c++

I would like to ask about casting in C++. I heard that when casting is ambiguous compiler should return an error, but, just for better understanding, I tested it and it didn't, moreover, it used functions in quite weird order. When:

A foo;
B bar = foo;

it used casting operator, but when I typed:

bar = static_cast<B>(foo);

it used single argument constructor.

Can anyone explain why it acts in this way?

The whole code which I used:

#include <iostream>
#include <typeinfo>

using namespace std;

class B;

class A {
public:
    A() {}
    A (const B& x);
    A& operator= (const B& x);
    operator B();
};

class B {
public:
    B() {}
    B (const A& x) {
        cout << "constructor B" << endl;
    }
    B& operator= (const A& x) {
        cout << "Assign B" << endl;
        return *this;
    }
    operator A() {
        cout << "Outer B" << endl;
        return A();
    }
};

A::A (const B& x) {
    cout << "constructor A" << endl;
}
A& A::operator= (const B& x) {
    cout << "Assign A" << endl;
    return *this;
}
A::operator B() {
    cout << "Outer A" << endl;
    return B();
}

int main ()
{
    A foo;

// First one
    B bar = foo;

    bar = foo;
    foo = bar;

// Second one    
    bar = static_cast<B>(foo);

    B bar2 = static_cast<B>(foo);
    foo = static_cast<A>(bar);
    B bar3 = foo;
    A foo2 = bar3;
    A foo3 = B();
    foo3 = B();

    return 0;
}

Edit:

My output:

Outer A
Assign B
Assign A
Copy constructor B
Copy constructor B
Copy constructor A
Outer A
Outer B
Outer B
Assign A
like image 408
Michał Ziobro Avatar asked Sep 15 '16 10:09

Michał Ziobro


1 Answers

The reason your compiler does not complain about ambiguity is that your constructors and assignment operators take a const A/B&, but operator A() and operator B() are not declared const. For the conversion of non-const objects, the compiler therefore prefers operator A/B().

I think that the rest can be explained with the rules of static_cast conversion, which in your code amounts to behavior as in direct initialization, and overload resolution (which is why the assignment operator is only called in the last example).

like image 132
acs Avatar answered Nov 15 '22 15:11

acs