Polymorphism and Inheritance
Archon

I put all objects in "Object[x]" by using the object superclass. How can I tell "Object[x]" to call the cChild classes after it has been constructor-ed as a cChild object?

Here is my code:

1#include <allegro.h>
2 
3// Superclass of all objects
4class cObject {
5 public:
6 cObject() {
7 allegro_message("Object created");
8 }
9
10 ~cObject() {
11 allegro_message("Object destroyed");
12 }
13
14 void something() {
15 allegro_message("Object called");
16 }
17
18};
19 
20// A custom defined object
21class cChild : public cObject {
22 public:
23 cChild() {
24 allegro_message("Child Created");
25 }
26
27 ~cChild() {
28 allegro_message("Child destroyed");
29 }
30 
31 void something() {
32 allegro_message("Child called");
33 }
34};
35 
36// Object Array
37cObject *Object[2];
38 
39// main
40int main() {
41 allegro_init();
42
43 allegro_message("MAIN(): New Objects - cChild");
44 Object[1] = new cChild();
45 Object[2] = new cChild();
46 
47 allegro_message("MAIN(): Object->something();");
48 Object[1]->something();
49 Object[2]->something();
50
51 allegro_message("MAIN(): delete Object[]");
52 delete Object[0];
53 delete Object[1];
54 delete Object[2];
55
56 allegro_exit();
57}
58END_OF_MAIN();

--- EDIT ---
The output is:

"MAIN(): New Objects - cChild"
"Object created"
"Child created"
"Object created"
"Child created"

"MAIN(): Object->something();"
"Object called"
"Object called"

"MAIN(): delete Object[]"
"Object destroyed"
"Object destroyed"

lucaz

there are some casting operators, like
dynamic_cast and static_cast,

I think that the array of pointers to cObject, cannot use anything from cChild, unless you define virtual methods or use a cast.

Thomas Fjellstrom

Don't you have to make the methods virtual? I think that'll fix it.

Archon

How would you make a constructor / destructor 'virtual'?

----- EDIT -----
making the superclass (cObject) void something() virtual, worked. I only need to put this on superclasses right?

Thomas Fjellstrom

I belive so. And maybe make the destructor virtual too... "I think"

class BaseClass {
   public:
      virtual ~BaseClass(); // not sure if thats valid though, I assume it is.
   ...
}

Archon

OK, I cannot make constructors virtual but I can make destructors virtual.
Also when I make destructors virtual, then both destructors are called.
So here is the code updated:

1#include <allegro.h>
2 
3// Superclass of all objects
4class cObject {
5 public:
6 cObject() {
7 allegro_message("Object created");
8 }
9
10 virtual ~cObject() {
11 allegro_message("Object destroyed");
12 }
13
14 virtual void something() {
15 allegro_message("Object called");
16 }
17
18};
19 
20// A custom defined object
21class cChild : public cObject {
22 public:
23 cChild() {
24 allegro_message("Child Created");
25 }
26
27 ~cChild() {
28 allegro_message("Child destroyed");
29 }
30 
31 void something() {
32 allegro_message("Child called");
33 }
34};
35 
36cObject *Object[0];
37 
38// main
39int main() {
40 allegro_init();
41
42 Object[0] = NULL;
43
44 allegro_message("MAIN(): New Objects - cChild");
45 Object[0] = new cChild();
46 
47 allegro_message("MAIN(): Object->something();");
48 Object[0]->something();
49
50 allegro_message("MAIN(): delete Object[]");
51 
52 delete Object[0];
53
54 allegro_exit();
55}
56END_OF_MAIN();

Output:
"MAIN(): New Objects - cChild"
"Object created"
"Child Created"

"MAIN(): Object->something();"
"Child called"

"MAIN(): delete Object[]"
"Child destroyed"
"Object destroyed"

Notes:
I put virtual on the superclass
- virtual void something();
- virtual ~cObject();

With constructors, cObject is called first then cChild's.
With destructors, cChild is called first then cObject's.

Code update compared with previous, I am only using 1 object now to make it easier...

Krzysztof Kluczek

1) you can't make constructors virtual since it's completely pointless - how should virtual constructor be different from non-virtual one?
2) base class constructor is always called before derivate class constructor and base class destructor is always called after derivate class destructor, no matter they are virtual or not

Archon

maybe I should just leave the constructors and destructors empty for superclasses then

ReyBrujo

In every destructor you should free memory allocated by that constructor. Don't make your child delete memory which was allocated by the base constructor, because you are likely forget to copy that code in another child destructor, generating a memory leak.

gillius

Yeah, use ctors/dtors for what they are useful for. In polymorphism, use them to initialize elements in that class alone.

Destructors should be virtual if you ever delete an object through a pointer-to-base type. Usually I make destructors always virtual if I'm using inheritance, just to be safe.

23yrold3yrold
Quote:

OK, I cannot make constructors virtual but I can make destructors virtual.

Quite right.

Quote:

With constructors, cObject is called first then cChild's.
With destructors, cChild is called first then cObject's.

Also quite right.

Quote:

maybe I should just leave the constructors and destructors empty for superclasses then

At least initialize all member variables. Wise practice.

So the problem is all solved then?

Krzysztof Kluczek

ReyBrujo is right. Some example should help understanding it.

class cBase {
 public:
  char *bunch_of_bytes;

  cBase() { bunch_of_bytes = new char[100]; }
  virtual ~cBase() { delete bunch_of_bytes; }
};

class cDerived : public cBase {
 public:
  char *another_bunch_of_bytes;

  cDerived() { another_bunch_of_bytes = new char[50]; }
  virtual ~cDerived() { delete another_bunch_of_bytes; }
};

Base class allocates some memory. When derived class constructor is called, it can assume that base class is fully initialized, since its constructor was called and allocated the memory. Now, derived class wants to allocate some more memory. Derived class destructor has only to free memory allocated in derived class constructor, since base class destructor gets called automatically after it and will free base class allocated memory.

[edit: forgot ': public cBase' in code]

decsonic

Just be shure you dont do anything like this with your destructors.

1CBaseClass
2{
3 public:
4 CBaseClass();
5 virtual ~CBaseClass();
6 
7 protected:
8 CSurface *m_Surface;
9}
10 
11CBaseClass::CBaseClass() : m_Surface(NULL)
12{
13 m_Surface = new CSurface;
14}
15 
16CBaseClass::~CBaseClass()
17{
18 delete m_Surface;
19}
20 
21CDervivedClass::CDervivedClass() : CBaseClass()
22{
23
24}
25//Up to now everything should be normal, but this constructor is wrong.
26CDervivedClass::~CDervivedClass()
27{
28 delete m_Surface;
29}
30 
31//General Rule is dont free anything from the memory that you did not create.

You could also implement the base class functions as pure virtual.

virtual void Jump(int Height) = 0;

Edit : Beaten by a few hours.. ah well.

Tobias Dammers

One more rule: If you have any virtual methods in a class, the destructor must be virtual, too. Otherwise, the child's destructor overwrites the parent's one, and the wrong destructors get called. At least, that's what my C++ book says.

23yrold3yrold
Quote:

One more rule: If you have any virtual methods in a class, the destructor must be virtual, too. Otherwise, the child's destructor overwrites the parent's one, and the wrong destructors get called. At least, that's what my C++ book says.

That's right, but for the wrong reason. The destructor should be virtual if you can expect the class to be derived from at some point, and virtual methods are generally a good indicator of that. :)

gillius

You are not required to make a destructor virtual in any circumstance, but it is good style to make the destructor virtual if any of its methods are virtual. But as long as you always know the exact type of an object when you delete it, then you don't need virtual destructors. But, if you are using virtual methods, then you probably don't know the type at delete time, so if you have virtual methods, 99% of the time you'll want virtual dtors as well.

Thread #382786. Printed from Allegro.cc