Virtual Assignment Operator C++

Why are virtual assignment operators a can of worms?

Let us take the classic shape example:

class Shape
{
public: virtual bool operator==(const Shape & s) const = 0;
};

class Rectangle : public Shape
{
public: bool operator==(const Shape & s) const
{ /*...*/ }
};

class Circle : public Shape
{
public: bool operator==(const Shape & s) const
{ /*...*/ }
};

Now comes the fun part.

Rectangle r;
Circle c;
Shape * p_shape1 = &r; // This is legal.
Shape * p_shape2 = &c; // So is this.

// What happens here????
if (r == *p_shape2)
{
//...
}

IMHO, operators should not be inherited. There is no guarantee that Child1's operators will be passed Child1 instances; They could be passed Child` or Child3 or even GrandChild1 instances.

C++ virtual assignment operator

Your problem might be that you define the class in a namespace, but you define the operators outside that namespace without specifying it. Because of this, the compiler can't connect the definition to the declaration.

Ishamael pointed out that you don't specify what happens when a non-Point Shape is assigned to a Point. This is necessary for a virtual assignment operator; see his answer. But this virtual assignment operator could end up doing a lot of unexpected things, like cutting off parts of objects if the wrong types are assigned to each other.

You don't need the virtualness to ensure that the Shape operator also gets called when Point is assigned. Just call the Shape operator inside the Point operator. Making the operator virtual would actually have the opposite effect; the Point operator would override the Shape operator even if the instance you're calling it with is referred to as a Shape.

Point& Point::operator = (const Point& source)    //assign
{
if (this == &source) //avoid self-assignment
return *this;
Shape::operator=(source); // also call the base class operator
m_x = source.m_x;
m_y = source.m_y;
return *this;
}

Pure virtual assignment operator in c++

Try it like this

#include <iostream>
#include <string>

using namespace std;

class Base {
public:
virtual ~Base() {}

};


class D1 : public Base {
public:
virtual ~D1() {}
//...some fields
//assignment operator, it does the deep copy of the members
D1& operator=(const D1&) {
cout << "D1:operator=(const D1&)\n";
return *this;
}
};

class D2 : public Base {
public:
virtual ~D2() {}
//...some fields
//assignment operator, it does the deep copy of the members
D2& operator=(const D2&) {
cout << "D2:operator=(const D2&)\n";
return *this;
}
};

main

    D1 *d1 = new D1();
D1 *d1_another = new D1();
//this doesn't work:
*d1 = *d1_another;

D2 *d2 = new D2();
D2 *d2_another = new D2();
//this doesn't work:
*d2 = *d2_another;

Why can't have I a pure virtual assignment operator?

The compiler generates an implicit copy-assignment operator that is being selected when you do a B = B assignment. That is not selected when you do a B = C assignment.

http://en.cppreference.com/w/cpp/language/copy_assignment

https://wandbox.org/permlink/CM5tQU656rnwtrKl

If you look at your error message:

/tmp/cctHhd0D.o: In function `B::operator=(B const&)':
prog.cc:(.text._ZN1BaSERKS_[_ZN1BaSERKS_]+0x1f): undefined reference to `A::operator=(A const&)'
collect2: error: ld returned 1 exit status

You can see that the linker error is from inside B::operator=(B const&), which, since you didn't define one, means it must be auto-generated.

C++: pure virtual assignment operator

From section 12.8 of the standard:

13 The implicitly-defined copy assignment operator for class X performs memberwise assignment of its subobjects. The
direct base classes of X are assigned first, in the order of their declaration in the base-specifier-list
, and then the immediate
non-static data members of X are assigned, in the order in which they were declared in the class definition. Each subobject
is assigned in the manner appropriate to its type:

— if the subobject is of class type, the copy assignment operator for the class is used (as if by explicit qualification;
that is, ignoring any possible virtual overriding functions in more derived classes);

The subclass is using the implicitly-defined copy assignment operator, and there is no definition of the base class's copy assignment operator, but it is declared, so you get a link error instead of a compilation error.

Polymorphism with virtual assignment operator

I believe it is because virtual int operator=(A& rIn) in class B is not the real default operator= so the compiler is creating a B& operator=(const B& other) for you and using that one.

To add to this, it is not enough to override your virtual operator=, you must also define the regular operator=.

And of course it is best to use C++11 features like the override keyword to guarantee that you actually wrote the function signature you meant to, instead of creating a new virtual function.



Related Topics



Leave a reply



Submit