Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Polymorphism and Inheritance

This thread is locked; no one can reply to it. rss feed Print
Polymorphism and Inheritance
Archon
Member #4,195
January 2004
avatar

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
Member #4,194
January 2004

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
Member #476
June 2000
avatar

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

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Archon
Member #4,195
January 2004
avatar

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
Member #476
June 2000
avatar

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.
   ...
}

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Archon
Member #4,195
January 2004
avatar

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
Member #4,191
January 2004
avatar

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
Member #4,195
January 2004
avatar

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

ReyBrujo
Moderator
January 2001
avatar

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.

--
RB
光子「あたしただ…奪う側に回ろうと思っただけよ」
Mitsuko's last words, Battle Royale

gillius
Member #119
April 2000

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.

Gillius
Gillius's Programming -- https://gillius.org/

23yrold3yrold
Member #1,134
March 2001
avatar

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?

--
Software Development == Church Development
Step 1. Build it.
Step 2. Pray.

Krzysztof Kluczek
Member #4,191
January 2004
avatar

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
Member #4,150
December 2003

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.

Programmer's paranoia: Don't trust anybody's code, not even your own.

Human Modeling Tutorials

Tobias Dammers
Member #2,604
August 2002
avatar

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.

---
Me make music: Triofobie
---
"We need Tobias and his awesome trombone, too." - Johan Halmén

23yrold3yrold
Member #1,134
March 2001
avatar

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. :)

--
Software Development == Church Development
Step 1. Build it.
Step 2. Pray.

gillius
Member #119
April 2000

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.

Gillius
Gillius's Programming -- https://gillius.org/

Go to: