Base class calling derived class methods

M

Mike C#

Suppose I have a base class "foo". Another class, "bar" derives from it.
Base class "foo" has a method called "rob_the_liquor_store()", and the
inherited class "bar" overrides this method with one of its own, maybe
specifying the liquor store over on 44th Street and 5th Avenue or something.

Anyway this is what we have so far:

base class: "foo"
|------------method: "rob_the_liquor_store()"
|
|
derived class: "bar" inherits from "foo"
|------------method: "rob_the_liquor_store()"

Now the question: If I add another method to "foo" (in keeping with
character, let's call it "commit_a_felony()"), can I specify that it should
call the inherited class's ("bar's") "rob_the_liquor_store()" method instead
of the base class's? If so, how?

Thanks
 
S

SvenC

Hi Mike,

Mike C# said:
Suppose I have a base class "foo". Another class, "bar" derives from it.
Base class "foo" has a method called "rob_the_liquor_store()", and the
inherited class "bar" overrides this method with one of its own, maybe
specifying the liquor store over on 44th Street and 5th Avenue or
something.

Anyway this is what we have so far:

base class: "foo"
|------------method: "rob_the_liquor_store()"
|
|
derived class: "bar" inherits from "foo"
|------------method: "rob_the_liquor_store()"

Now the question: If I add another method to "foo" (in keeping with
character, let's call it "commit_a_felony()"), can I specify that it
should call the inherited class's ("bar's") "rob_the_liquor_store()"
method instead of the base class's? If so, how?

Technically yes, but if you are in such a situation to need this is looks
like you should reconsider your class design.

First: you have to be sure that while you are in a method of foo your
instance is at least a bar instance or further derived otherwise your bar
method can "get upset" as it executes without the proper class layout it
expects. E.g. if bar has an instance member this will only be valid if you
have a bar instance otherwise it will be random memory.

So you can but should not do this in a foo method:
((bar*)this)->commit_a_felony()
 
M

Mike C#

OK, thanks. The reason I ask is because I have classes that actually look
more like this:

base class: "foo"
|------------method: connect_to_db()
|
|>>>>derived class: "bar_1"
| |------------method: init_columns()
|
|>>>>derived class: "bar_2"
| |------------method: init_columns()

The connect_to_db() method of foo is inherited by the bar_n classes. This
method just opens a database connection, and each derived class can use the
common inherited connect_to_db() method without change. The init_columns()
method of each derived class contains some code specific to the bar_n()
object, and this method can't be implemented (afaik) in "foo". I'd like to
cut down on some code and call init_columns() and some other functions that
had to be implemented in foo directly from connect_to_db(), but it's
implemented only in foo. The reason I'd like to do this is that I'm
noticing a lot of repetitive code in some of these methods, which I'd like
to eliminate.

Thanks
 
S

SvenC

Hi Mike,

Mike C# said:
OK, thanks. The reason I ask is because I have classes that actually look
more like this:

base class: "foo"
|------------method: connect_to_db()
|
|>>>>derived class: "bar_1"
| |------------method: init_columns()
|
|>>>>derived class: "bar_2"
| |------------method: init_columns()

The connect_to_db() method of foo is inherited by the bar_n classes. This
method just opens a database connection, and each derived class can use
the common inherited connect_to_db() method without change. The
init_columns() method of each derived class contains some code specific to
the bar_n() object, and this method can't be implemented (afaik) in "foo".
I'd like to cut down on some code and call init_columns() and some other
functions that had to be implemented in foo directly from connect_to_db(),
but it's implemented only in foo. The reason I'd like to do this is that
I'm noticing a lot of repetitive code in some of these methods, which I'd
like to eliminate.

This is how you solve it in a correct way

class foo
{
public:
virtual void init_columns() = 0; // = 0 means pure virtual so derivers
must implement this
void connect_to_db();
};

class bar_1 : public foo
{
public:
void init_columns()
{
// implement the bar_1 version
}
};

void main()
{
foo *f = new bar_1();
f->connect_to_db(); // calls foo's method
f->init_columns(); // calls bar_1's method
}

So that is a classic use case for pure virtual functions.
 
M

Mike C#

Thanks SvenC, tell me though - will this pattern work? This is a little
closer to what I'm trying to do:

class foo
{
public:
void connect_to_db();
protected:
virtual void init_columns() = 0;
};

void foo::connect_to_db()
{
this->init_columns();
}

class bar_1 : public foo
{
public:
void init_columns()
{
// implement the bar_1 version
}
};

class bar_1 : public foo
{
public:
void init_columns()
{
// implement the bar_2 version
}
};

void main()
{
foo *f1 = new bar_1();
f1->connect_to_db();
foo *f2 = new bar_2();
f2->connect_to_db();
}

I noticed in main() you declare a pointer to foo and instantiate it as a
bar_n type. I just want to make sure I'm reading that correctly :) Thanks
again!
 
T

Tom Widmer [VC++ MVP]

Mike said:
Thanks SvenC, tell me though - will this pattern work? This is a little
closer to what I'm trying to do:

class foo
{
public:
void connect_to_db();
protected:
virtual void init_columns() = 0;
};

void foo::connect_to_db()
{
this->init_columns();
}

class bar_1 : public foo
{
public:
void init_columns()
{
// implement the bar_1 version
}
};

class bar_1 : public foo
{
public:
void init_columns()
{
// implement the bar_2 version
}
};

void main()
{
foo *f1 = new bar_1();
f1->connect_to_db();
foo *f2 = new bar_2();
f2->connect_to_db();
}

I noticed in main() you declare a pointer to foo and instantiate it as a
bar_n type. I just want to make sure I'm reading that correctly :) Thanks
again!

Your code looks fine (apart from the memory leaks, and lack of a virtual
destructor on foo - I'm sure you'll fix both problems in the real
code!). This idea is the basis of a design pattern, "Template Method":
http://en.wikipedia.org/wiki/Template_method_pattern

Tom
 
M

Mike C#

Cool, thanks for the heads up. Also do I have to declare them like this:

foo *f1 = new bar_1();

Or can I use it like this:

bar_1 b1;
b1.connect_to_db();

Thanks
 
C

Carl Daniel [VC++ MVP]

Mike C# said:
Cool, thanks for the heads up. Also do I have to declare them like this:

foo *f1 = new bar_1();

Or can I use it like this:

bar_1 b1;
b1.connect_to_db();

either will work and they'll do exactly the same thing.

-cd
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top