Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ dynamic casting

I have a main abstract class that I am provided and must create subclasses based on this class (THIS CANNOT BE MODIFIED):

class Spaceship
{
  protected:
    string m_name;      // the name of the ship
    int m_hull;         // the hull strenght
  public:

    // Purpose: Default Constructor
    // Postconditions: name and hull strength set to parameters
    // -- INLINE
    Spaceship(string n, int h)
    {
      m_name = n;
      m_hull = h;
    }

    // Purpose: Tells if a ship is alive.
    // Postconditions: 'true' if a ship's hull strength is above zero,
    //                 'false' otherwize.
    // -- INLINE
    bool isAlive()
    {
      return (m_hull > 0);
    }

    // Purpose: Prints the status of a ship.
    // -- VIRTUAL
    virtual void status() const = 0;

    // Purpose: Changes the status of a ship, when hit by a
    //    weapon 's' with power level 'power'
    // -- VIRTUAL
    virtual void hit(weapon s, int power) = 0;

    string getName() const
    {
      return m_name;
    }

}; //Spaceship

So is an example of my child classes:

class Dreadnought: public Spaceship
{
  int m_shield;
  int m_armor;
  int m_type;
  public:
    Dreadnought( string n, int h, int a, int s ): Spaceship( n, h ),m_shield( s ),m_armor(a),m_type(dreadnought){}
    virtual void status() const
    {
      // implementation not shown to save space
    }
    virtual void hit(weapon s, int power)
    {
      // implementation not shown to save space
    }

    int typeOf(){ return m_type; }
};

in my main code I have an dynamic array of different types of Spaceships:

Spaceship ** ships;

cin >> numShips;

// create an array of the ships to test
ships = new Spaceship * [numShips];

Then i get input from the user to declare different types of ships in this array like:

ships[0] = new Dreadnought( name, hull, armor, shield );

my question is when I go to delete the array the correct destructor is not called, instead Spaceships is called, will this create a memory leak because the member vars "m_shield, m_armor" are not deleted and left hanging? If so is there a better way to get the type than using a var m_type and calling:

if( ships[i]->typeOf() == 0 )
      delete dynamic_cast<Frigate*>(ships[i]);
    else if( ships[i]->typeOf() == 1 )
      delete dynamic_cast<Destroyer*>(ships[i]);
    else if( ships[i]->typeOf() == 2 )
      delete dynamic_cast<Battlecruiser*>(ships[i]);
    else if( ships[i]->typeOf() == 3 )
      delete dynamic_cast<Dreadnought*>(ships[i]);
    else
      delete dynamic_cast<Dropship*>(ships[i]);

Question #2 in the Spaceship class i declared: virtual int typeOf() = 0; and commented it out, is there a way i can implement this function in the child classes without declaring in the parent class so i can use it like shown above? when i dont declare it i get the compiler error:

error: 'class Spaceship' has no member named 'typeOf'

I assume this again has something to do with dynamic casing.

any help would be great,

Thanks nat

edit:

to clairify my first question would i have a memory leak if I just did:

delete ships[i];

or should i do:

delete dynamic_cast(ships[i]);

to remove member vars that are only in the derived classes?

Thnaks

like image 316
nat45928 Avatar asked Jan 17 '26 07:01

nat45928


1 Answers

You must add a virtual destructor to your Spaceship class. Then delete will properly destroy the elements from the array.

You must declare the typeOf() method in Spaceship. Otherwise, the compiler cannot know, that this is a valid member function.

You can avoid typeOf(), if you add the needed functionality as virtual member functions in your base class.

And even if you cannot modify your base class for whatever reasons, you can just do the dynamic_cast and test, if it yields a null pointer

Frigate *p = dynamic_cast<Frigate*>(ships[i]);
if (p != 0) {
    // do something with a frigate
}
like image 94
Olaf Dietsche Avatar answered Jan 20 '26 02:01

Olaf Dietsche



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!