Search code examples
c++classinheritancesuperclass

Why access from child class to the field of other exemplar of superclass crashed this field?


Inside second extender class, when called method clone(s) value of field is changing.

Listing:

#include<iostream>
using namespace std;
class Set
{
public:
    Set(int min,int max)
    {
        num_bits=max-min+1;
        num_bytes=(num_bits+7)/8;
        elems=new int8_t[num_bytes];
        for(int i=0; i<num_bytes; i++)elems[i]=0;
        minElem=min;
        maxElem=max;
    };

    void add(int n)
    {
        int bit=n-minElem;
        elems[bit/8]|=(1<<(bit%8));
    };

    void del(int n)
    {
        int bit=n-minElem;
        elems[bit/8]&=~(1<<(bit%8));
    };

    bool has(int n)
    {
        int bit=n-minElem;
        return(elems[bit/8]&(1<<(bit%8)));
    }

    void print()//str
    {
        int i=0;
        do
        {
            cout<<(has(i+minElem)?"1":"0");
            i++;
            if(i%8==0)cout<<" ";
        }
        while(i<num_bits);
    }

    ~Set()
    {
        delete[] elems;
    };

public://rotected
    int num_bits,num_bytes,minElem,maxElem;
    int8_t *elems;
};

class ExSet:public Set{
    public:
    ExSet(int min,int max):Set(min,max){}
    ExSet(Set s):Set(s.minElem,s.maxElem){/*clone(s);*/}
    void clone(Set s){
    //for(int i=0;i<num_bytes;i++){int x=s.elems[i];cout<<elems[i]<<'='<<s.elems[i]<<'/';}
    };
};

main()
{
    char *p="ABCZabxyz";
    Set s('A','z');
    do s.add(*p);
    while(*++p!='\0');
    s.del('B');
    s.print();
    cout<<endl;
    for(char c='A'; c<='z'; c++)if(s.has(c))cout<<c;
    cout<<endl;
    //delete &s;
    ExSet es(s);
    for(char c='A'; c<='z'; c++)if(s.has(c))cout<<c;
};

Expected:

10100000 00000000 00000000 01000000 11000000 00000000 00000001 11
ACZabxyz
ACZabxyz

Get:

10100000 00000000 00000000 01000000 11000000 00000000 00000001 11
ACZabxyz
FGINQRVWghqrvw

Solution

  • The following line is the source of your memory problems.

    ExSet(Set s):Set(s.minElem,s.maxElem){/*clone(s);*/}
    

    When you execute

    ExSet es(s);
    

    a temporary copy of s is made in the call to the constructor of ExSet. When that temporary is destructed, it deletes the memory held by elems.

    When s is destructed, the same memory is again deleted. That leads to undefined behavior. In your case, it produces wrong results. In other cases, the program might crash.

    You can resolve this particular problem by using

    ExSet(Set const& s):Set(s.minElem,s.maxElem){/*clone(s);*/}
    

    However, for a proper fix, provide a copy constructor and a copy assignment operator in Set. To understand why, look up the Rule of Three.