Question

This problem is really odd, I can't seem to find anything that causes it.

So here is an assignment operator overloading function, birds and mammals are vectors. (down below are the classes)

const Register& Register::operator=(const Register& theOther)
{
    if(this != &theOther)
    {
        this->~Register();               // deleted
        birds.resize(theOther.birds.size());
        mammals.resize(theOther.mammals.size());

        birds=theOther.birds;
        mammals=theOther.mammals;
    }
    return *this;
}

(if you find anything that is weird here, that is because I rewrote these lines many times). So the problem is while running, the

birds.operator=(theOther.birds);

works absolutely fine, every variable is copied properly, but when it reaches the next line, it calls the same vector copying function as with the birds, but mammals never gets theOther.mammals -es Animal parts (species, etc.). It gets the only mammal parts (predator, etc.). I just don't understand. Below are my classes, and as you can see, they are completely similar at the parts which are important here...

So, the classes

class Animal
{
    char* species;
    unsigned int weight;
    char* color;
public:
...
}

The bird class

class Bird: public Animal
{
    bool singing;
    bool waterfowl;
    unsigned int eggs; 

public:
...
const Bird& operator =(const Bird& theOther);
{
    if(this != &theOther)
    {
        Bird copy(theOther);
        this->setSpecies(copy.getSpecies());
        this->setWeight(copy.getWeight());
        this->setColor(copy.getColor());

        singing = theOther.singing;
        waterfowl = theOther.waterfowl;
        eggs = theOther.eggs;
    }
    return *this;
}

The mammal class

class Mammal: public Animal
{
    bool predator;
    bool oviparous;
public:
...
const Mammal& Mammal::operator =(const Mammal& theOther)
{
    if(this != &theOther)
    {
        Mammal copy(theOther);
        this->setPredator(copy.getPredator());
        this->setOviparous(copy.getOviparous());

        predator = theOther.predator;
        oviparous = theOther.oviparous;
    }
    return *this;
}

And of course the Register, which has the vectors.

class Register
{
    std::vector <Bird> birds;
    std::vector <Mammal> mammals;
    std::vector <Reptile> reptiles;

public:
...

edit:

Register::Register(const Register& newRegister)
{
    birds = newRegister.birds;
    mammals = newRegister.mammals;
    reptiles = newRegister.reptiles;
}

edit2:

void Animal::setSpecies(char* _species)
{
    this->species = _species;
}

Maybe I'm just too tired to find the mistake that I made. Please tell me what I did wrong.

Was it helpful?

Solution

As stated before - don't call the destructor manually.

The reason your mammal operator= doesn't copy the species, weight and color while your bird operator= does is because the mammal version doesn't have the code that sets those value. The bird operator has these lines:

    this->setSpecies(copy.getSpecies());
    this->setWeight(copy.getWeight());
    this->setColor(copy.getColor());

the mammal operator does not.

Either copy those lines into the mammal operator or, better still, write a method of animal that does it and call it from both bird and mammal operators.

I am also not sure why you need to make a copy before calling getSpecies etc, you should be able to call it on the original theOther parameter.

OTHER TIPS

Your code has undefined behaviour. After you call this->~Register();, you must not access any members of this. You should simply remove that line, and everything will be fine (although perhaps not exception safe).

If you want strong exception safety, you should implement operator= using the copy-and-swap idiom:

const Register& Register::operator=(Register theOther)
{
    std::swap(*this, theOther);
    return *this;
}

Furthermore, the operator= in your subclasses should call through to the operator= in the super-class. You can do this manually with a call to Animal::operator=, or you can again use copy-and-swap for strong exception safety.

Mammal& Mammal::operator=(const Mammal& theOther)
{
    if(this != &theOther)
    {
        static_cast<Animal&>(*this) = theOther; //Call Animal::operator=
        predator = theOther.predator;
        oviparous = theOther.oviparous;
    }
    return *this;
}

//Or use:
Mammal& Mammal::operator=(Mammal theOther)
{
    std::swap(*this, theOther);
    return *this;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top