views:

93

answers:

5

can somebody please help me with an error

conversion from `A' to non-scalar type `B' requested

I have class A and derived from it B, but I have problems with these rows:

A a(1);
A *pb = new B(a);
B b = *pb;    //here I have an error

thanks in advance for any help

class A {
protected:
    int player;
public:
    A(int initPlayer = 0);
    A(const A&);
    A& operator=(const A&);
    virtual ~A(){};
    virtual void foo();
    void foo() const;
    operator int();
};

class B: public A {
public:
    B(int initPlayer): A(initPlayer){};
    ~B(){};
    virtual void foo();
};

edited

I have this code and (I can't change it):

A a(1);
A *pb = new B(a);
B b = *pb;    

I tried to create constructor for B:

B::B(const A & a):
    player(a.player){}

B& B::operator=(const A& a){
    if(this == &a){
        return *this;
    }
    player = a.player;
    return *this;
}

but it gives me an error, really need help from professionals

+5  A: 

Your problem is due to static type checking. When you have this line:

A *pb = new B(a);

The static type of pb is A * and it's dynamic type is B *. While the dynamic type is correct, the compiler is checking the static type.

For this simple code, since you know the dynamic type of pb is always a B, you can fix this with a static cast:

B b = *static_cast<B *>(pb); 

But be warned that if the dynamic type of pb was an A * the cast would cause undefined behavior.

R Samuel Klatchko
do I have another way to solve this problem, without casting? it will be very helpful
lego69
@lego69 - one common technique is to create a virtual `clone` method and have every class override it. Beyond that, I can't answer without knowing *why* you are trying to copy your object.
R Samuel Klatchko
A: 

In such situations a dynamic cast is most appropriate. Dynamic cast will invoke the runtime type system to figure out the "real" type of bp and will return 0 if it can't be cast to the requested type. As you know the real type you could also use static_cast here but generally this isn't the case in such situations.

 B* b = dynamic_cast<B*>(pb);
pmr
+1  A: 

When you dereference an 'A' pointer, you get an 'A' even if it points to a 'B'. Polymorphism does not come into play here! To preserve the 'B' properties to the 'A' object you should properly cast the initialization as explained in some of the other answers.

Amardeep
It's not an assignment operator that's required here but a copy constructor.
Troubadour
@Amardeep: can You give me please example, I'm beginner, I understood what you said, but it is a little bit difficult to write it
lego69
@Troubadour: Thank you, I've updated the answer.
Amardeep
@lego69: Please disregard my previous suggestion. It was too specialized for this particular example and not true in general. If you use a copy constructor or assignment operator that takes 'A' to create/assign a 'B', it will lose the 'B' properties of the derived object the 'A' pointer represented.
Amardeep
A: 

*pb will give you a A& and not a B&. It's just like pb being an A* and not a B* even though the actual object is a B.

B b = *pb will attempt to copy-construct a B using a synthesised copy constructor. The copy constructor will therefore be looking for a B& as its argument. You have no constructor to make a B from an A, hence the error.

As @R Samuel Klatchko says you could just cast it or, in the case you've given, you could just make pb actually be a B*.

Troubadour
@Troubadour: can You please give me an example how can create copy constructor for B, I created it, but I receive an error
lego69
@lego69: I doubt that that is what you want, it is just the source of your compiler error. You are trying to make a complete clone of the original `B` object, yes? I was going to update my answer earlier to suggest a `clone` method but that's already been suggested by @R Samuel Klatchko. That is probably what you want _assuming_ you really want a copy of the object and that a reference or pointer to the original wouldn't do. Without knowing how `b` is going to be used it's difficult to say.
Troubadour
A: 

You are trying to assign an object of type A to object of type B. Which is not allowed unless you define a type cast operator. pb is a pointer to A object and in general it is not a pointer to B (in your case it is, but it doesn't matter for the compiler, since it's declared as pointer to A). To make such assignement possible, you first need to down-cast pb to pointer of B (as R Samuel Klatchko pointed out, in your case static_cast is perfectly fine; in other cases you might need use dynamic_cast).

a1ex07