Polymorphism & Assignment Operator Overloading

So I'm totally confused about how to go about this. I have something like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class parent {
  public:
    virtual parent& operator=(const parent&)=0;

};

class child : public parent {
  public:
    virtual parent& operator=(const parent&);
  protected:
    string s;
    int i;
};

parent& child::operator=(const parent& that)
{
    *this.s = that.s;
    *this.i = that.i;
}


This is completely wrong. I was reading around various places and it seems that I need to set the type of 'that' to be child, but that is const so how would I do that?
virtual child& operator=(const child&);
but then the parent operator= is not defined in the class that inherits it so the inheriting class is abstract.
Oh, doh.

In this case, I think operator = shouldn't be pure virtual, instead for the parent class make it just virtual with a do nothing body (since parent has no members).
The candidate function is still the parent operator= though right? So do I define it in the derived class with no code and then define the child operator=? Because I'm not aware that it will execute the child operator= in place of the parent operator= during run time.

From what I've been searching, this type of functionality isn't so straight forward. I should probably look at another way of implementation.
You shouldn't have a virtual assignment operator.

Consider the following:

1
2
3
4
5
6
7
// assume childA and childB are derived from parent
//   and parent has a virtual assignment operator

parent* a = new childA;
parent* b = new childB;

*b = *a;  // !!  explode! 


With a virtual assignment operator, that will compile OK, but the consequences will be dire.

An assignment should only progress if you know for a fact the two types are the same. And if you know for a fact the two types are the same, then you don't need polymorphism.
That's no reason to not declare it virtual. As long as derived classes only overload, not override, there shouldn't be a problem.
What I'm trying to say is, there's no reason to declare operator=() as virtual, but it, in itself, doesn't hurt.
You can always do something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#include <iostream>
using namespace std;    

class D1;
class D2;

class B
{
    public:
        
    B & operator=(const B & b)
    {
        if (type()!=b.type()) 
        {
            cerr<< "type mismatch in assignment operation\n";
            return *this;
        }
        
        return *( (B*) (AF[type()](this,&b)) );
    }    

    protected:
 
    virtual int type()const {return 0;}
    
    static B * assignB(B * dest,const B * source);
    static D1 * assignD1(D1 * dest,const D1 * source);
    static D2 * assignD2(D2 * dest,const D2 * source);
    
    typedef void * (*assignment_func)(void*,const void*);
    static const assignment_func AF[3];
    
    private:
    int val;

};

const B::assignment_func B::AF[3]={
    (assignment_func)assignB,
    (assignment_func)assignD1,
    (assignment_func)assignD2};

class D1:public B
{
    public:
    D1 & operator=(const B & b){return (D1&)((B&)*this=b);}
    
    private:
    int val1;    
    
    int type()const {return 1;}
    
    friend D1 * B::assignD1(D1 * dest,const D1 * source);
    
};

class D2:public B
{
    public:
    D2 & operator=(const B & b){return (D2&)((B&)*this=b);}
  
    private:
    int val2;
    
    int type()const {return 2;}
    
    friend D2 * B::assignD2(D2 * dest,const D2 * source);
};    

B * B::assignB(B * dest,const B * source)
{
    cout << "Base=Base" << endl;
    dest->val=source->val;
    return dest;
}

D1 * B::assignD1(D1 * dest,const D1 * source)
{
    cout << "Derived1=Derived1" << endl;
    dest->val=source->val;
    dest->val1=source->val1;
    return dest;
}    

D2 * B::assignD2(D2 * dest,const D2 * source)
{
    cout << "Derived2=Derived2" << endl;
    dest->val=source->val;
    dest->val2=source->val2;
    return dest;
}

int main()
{   
    B b;
    D1 d1;
    D2 d2;
    
    B * array[]={&b,&d1,&d2};
    
    int i,j;
    for (i=0; i<3; i++)
    {
        for (j=0; j<3; j++)
            *array[i]=*array[j]; 
    }
    
    cout << endl;
    
    b=b;
    d1=d1;
    d2=d2;
    
    b=d1;
    d2=b;
    d1=d2;
    
    system("pause");
    return 0;
}
Last edited on
Topic archived. No new replies allowed.