Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pointer cast while pass by referance

Tags:

c++

Look at my code, I can cast GoodMan pointer to a Man pointer and pass in to AddMan function using two steps. But when I uses one step to do that, It doesn't work. Instead, It needs to cast to the Man pointer reference explicitly not only to the Man pointer. What is the reason behind this?

    class Man{
    };

    class GoodMan: public Man
    {
    };

    void AddMan(Man*& man){};

    int main()
    {
        GoodMan* good_man = new GoodMan() ;

        //This works
        Man* pMan2 = (Man*)good_man;    
        AddMan(pMan2);

        //So I think this should work, But doesn't work
        AddMan((Man*)good_man);

        //But this works
        AddMan((Man*&)good_man);

        return 0;
    }
like image 497
Nayana Adassuriya Avatar asked Dec 12 '22 02:12

Nayana Adassuriya


2 Answers

C++ doesn't allow binding rvalues (bacically temporaries) such s (Man*)good_man to non-const lvalue references such as Man*&. In your code, pMan2 is an lvalue, so this can bind to the non-const reference parameter of AddMan. But (Man*)good_man is an rvalue. This is the cause of the error.

If you change the signature of AddMan to take a const lvalue reference, your code would compile.

void AddMan(Man* const& man){};

Of course, this doesn't allow you to change the pointer passed as argument. On the other hand, your solution, to cast to lvalue reference, "works" as far as making the code compile. But you have to ask yourself what it would mean to modify the pointer inside of the AddMan function.

AddMan((Man*&)good_man); // "works" by pretending everything is OK. It isn't.
like image 146
juanchopanza Avatar answered Dec 27 '22 16:12

juanchopanza


AddMan((Man*&)good_man); causes undefined behaviour. This is aliasing a GoodMan * as a Man * which is not permitted. It is a reinterpret_cast.

Although GoodMan is derived from Man , GoodMan * is not "derived" from Man *, they are incompatible types.

Example:

AddMan(static_cast<Man*&>(good_man));   // error: invalid static_cast

AddMan(reinterpret_cast<Man*&>(good_man));   // no error, but runtime UB

To help "sniff out" this problem, think about the void AddMan(Man*& man); function. It accepts a reference to Man *. It has to be called with a variable that is actually a Man *. The reference has to bind to a Man * specifically. In your original code, what has the reference bound to? good_man is not a Man *.

like image 38
M.M Avatar answered Dec 27 '22 17:12

M.M