1

Is there any difference if I were to comment out virtual before the destructor and Clone() functions in each derived class? They both produce the same output:

#include <iostream>

class Mammal

{

public:

    Mammal():itsAge(1) { std::cout << "Mammal constructor...\n"; }

    virtual ~Mammal() { std::cout << "Mammal destructor...\n"; }

    Mammal (const Mammal & rhs);

    virtual void Speak() const { std::cout << "Mammal speak!\n"; }

    virtual Mammal* Clone() { return new Mammal(*this); } 

    int GetAge()const { return itsAge; }



protected:

    int itsAge;

};



Mammal::Mammal (const Mammal & rhs):itsAge(rhs.GetAge())

{

    std::cout << "Mammal Copy Constructor...\n";

}



class Dog : public Mammal

{

public:

    Dog() { std::cout << "Dog constructor...\n"; }

    /*virtual*/   ~Dog() { std::cout << "Dog destructor...\n"; }

    Dog (const Dog & rhs);

    void Speak()const { std::cout << "Woof!\n"; }

    /*virtual*/  Mammal* Clone() { return new Dog(*this); }

};



Dog::Dog(const Dog & rhs):

Mammal(rhs)

{

    std::cout << "Dog copy constructor...\n";

}



class Cat : public Mammal

{

public:

    Cat() { std::cout << "Cat constructor...\n"; }

    /*virtual*/ ~Cat() { std::cout << "Cat destructor...\n"; }

    Cat (const Cat &);

    void Speak()const { std::cout << "Meow!\n"; }

    /*virtual*/   Mammal* Clone() { return new Cat(*this); }

};



Cat::Cat(const Cat & rhs):

Mammal(rhs)

{

    std::cout << "Cat copy constructor...\n";

}



enum ANIMALS { MAMMAL, DOG, CAT};

const int NumAnimalTypes = 3;

int main()

{

    Mammal *theArray[NumAnimalTypes];

    Mammal* ptr;

    int choice,i;

    for (i = 0; i<NumAnimalTypes; i++)

    {

        std::cout << "(1)dog (2)cat (3)Mammal: ";

        std::cin >> choice;

        switch (choice)

        {

        case DOG: 

            ptr = new Dog;

            break;

        case CAT: 

            ptr = new Cat;

            break;

        default: 

            ptr = new Mammal;

            break;

        }

        theArray[i] = ptr;

    }

    Mammal *OtherArray[NumAnimalTypes];

    for (i=0;i<NumAnimalTypes;i++)

    {

        theArray[i]->Speak();

        OtherArray[i] = theArray[i]->Clone();

    }

    for (i=0;i<NumAnimalTypes;i++)

        OtherArray[i]->Speak();

    return 0;

}
sth
  • 222,467
  • 53
  • 283
  • 367
Quaxton Hale
  • 2,460
  • 5
  • 40
  • 71

2 Answers2

1

Nope, there would be no difference.

The derived classes automatically get a virtual property if they inherited the upper class's virtual function. They are virtual even if you don't explicitly announce it.

richard.g
  • 3,585
  • 4
  • 16
  • 26
0

In the example you showed there would be no difference.

In general should the base class and derived classes had memory allocation / resource allocations, than you'd need to be more carefully with destructors and use virtual destructors to also call base class cleanup.

Consider:

class Base 
{
    // some virtual methods
};

class Derived : public Base
{
    ~Derived()
    {
        // Do some important cleanup
    }
}

Base *b = new Derived();
delete b;

In the scenario above when calling delete b, you'd invoke the destructor of the base class and no the destructor of the derived class and hence could lead to resource leaks.

So in your scenario there is no difference, since the base class declares the virtual keyword for those functions, however, should you remove it from the base class you will encounter problems such as described in my scneario above.

And specifically in your case the printouts will obviously change from cat/dog/etc.. to mammal, if the base class will have no virtual keyword for clone and for the copy constructor.

Max Shifrin
  • 809
  • 9
  • 24