Switching obect's type--sort of.

J

Joseph Cook

I was wondering if there was any way to do the following:

If I have a class Base, and multiple Derived classes which all have
some different behavior on some function foo()...is there any good way
to have an object that can switch between these various
functionalities..using a pointer to the generic class?

as follows:

class Status
{
Status(){}

Base *mode;
Derived1 derived1;
Derived2 derived2;
};

class Base
{
virtual foo();
};

class Derived1 : public Base
{
foo(){cout<<"One";}
};

class Derived2 : public Base
{
foo(){cout<<"Two";}
};

Such that I can change *mode so that I can call mode->foo(), and can
expect to be able to choose whether mode->foo() is calling Derived1's
foo, or Derived2's foo. Is there any way to create such behavior?

Thanks!
 
K

Karl Heinz Buchegger

Joseph said:
I was wondering if there was any way to do the following:

If I have a class Base, and multiple Derived classes which all have
some different behavior on some function foo()...is there any good way
to have an object that can switch between these various
functionalities..using a pointer to the generic class?

as follows:

class Status
{
Status(){}

Base *mode;
Derived1 derived1;
Derived2 derived2;
};

class Base
{
virtual foo();
};

class Derived1 : public Base
{
foo(){cout<<"One";}
};

class Derived2 : public Base
{
foo(){cout<<"Two";}
};

Such that I can change *mode so that I can call mode->foo(), and can
expect to be able to choose whether mode->foo() is calling Derived1's
foo, or Derived2's foo. Is there any way to create such behavior?

Not sure I understand what you want, but

void Status::bar()
{
mode = &derived1;
mode->foo(); // calls Derived1::foo

mode = &derived2;
mode->foo(); // calls Derived2::foo
}
 
C

Christian Stigen Larsen

Quoting Joseph Cook <[email protected]>:
| Such that I can change *mode so that I can call mode->foo(), and can
| expect to be able to choose whether mode->foo() is calling Derived1's
| foo, or Derived2's foo. Is there any way to create such behavior?

I'm a bit baffled, since you almost have it. Do you fully understand the
notion of virtual functions? Briefly, virtual functions enable _old_ code to
call _new_ code. This is all in the FAQ, in the section on inheritance and
virtuals:

http://www.parashift.com/c++-faq-lite/

In Status, just skip the derived1 and derived2 members:

class Status {
Base* mode;
public:
Status() : mode(0) {
}

void switchmode(Base* m) {
mode = m;
}

void dosomething() {
if ( mode ) mode->foo();
}
};

Then you could use your code like this:

Status s;
Derived1 d1;
Derived2 d2;
s.switchmode(d1);
s.dosomething(); // calls d1::foo()
s.switchmode(d2);
s.dosomething(); // calls d2::foo()
 
C

Chris Theis

Joseph Cook said:
I was wondering if there was any way to do the following:

If I have a class Base, and multiple Derived classes which all have
some different behavior on some function foo()...is there any good way
to have an object that can switch between these various
functionalities..using a pointer to the generic class?

as follows:

class Status
{
Status(){}

Base *mode;
Derived1 derived1;
Derived2 derived2;
};

class Base
{
virtual foo();
};

class Derived1 : public Base
{
foo(){cout<<"One";}
};

class Derived2 : public Base
{
foo(){cout<<"Two";}
};

Such that I can change *mode so that I can call mode->foo(), and can
expect to be able to choose whether mode->foo() is calling Derived1's
foo, or Derived2's foo. Is there any way to create such behavior?

Thanks!

I guess what you're looking for is not the object's type but the
implementation. In principle this problem is tackled by the "Strategy Design
Pattern" of which Karl Heinz has given you a basic example. I'd recommend to
check out any decent Design Pattern book or try my friend google.

HTH
Chris
 
K

Karl Heinz Buchegger

Chris said:
I guess what you're looking for is not the object's type but the
implementation. In principle this problem is tackled by the "Strategy Design
Pattern" of which Karl Heinz has given you a basic example.

Honestly I don't understand what the OP is asking about.
It's all there in his example:
* a pointer to base
* virtual functions.
all that's missing is the assignment, but that seems to be so trivial
that I think we are barking up the wrong tree and the OP has a completely
different problem but didn't express himself clearly enough.
 
L

lilburne

Karl said:
Honestly I don't understand what the OP is asking about.
It's all there in his example:
* a pointer to base
* virtual functions.
all that's missing is the assignment, but that seems to be so trivial
that I think we are barking up the wrong tree and the OP has a completely
different problem but didn't express himself clearly enough.

I think he wants to call either of the derived class methods from base
irrespective of the actuall object type, but I could be wrong.
 
C

Chris Theis

lilburne said:
I think he wants to call either of the derived class methods from base
irrespective of the actuall object type, but I could be wrong.

I guess this really calls for some clarification of the OP!

Chris
 
H

Howard

Joseph Cook said:
I was wondering if there was any way to do the following:

If I have a class Base, and multiple Derived classes which all have
some different behavior on some function foo()...is there any good way
to have an object that can switch between these various
functionalities..using a pointer to the generic class?

as follows:

class Status
{
Status(){}

Base *mode;
Derived1 derived1;
Derived2 derived2;
};

class Base
{
virtual foo();
};

class Derived1 : public Base
{
foo(){cout<<"One";}
};

class Derived2 : public Base
{
foo(){cout<<"Two";}
};

Such that I can change *mode so that I can call mode->foo(), and can
expect to be able to choose whether mode->foo() is calling Derived1's
foo, or Derived2's foo. Is there any way to create such behavior?

Thanks!

Your example does not seem to match what you've stated that you want.

In your example, you have three separate objects: one is of the base type,
the others are of the other two derived types. In the example, you could
just call derived1->foo() or derived2->foo(), based on whatever condition
you chose. The mode pointer isn't even needed, unless you also want to call
the Base class' foo function (via mode->foo()).

But, from your comments, it seems like you don't want three objects, but
rather a single object that can act as any of the derived classes. If you
actualy want to change an existing Base object from behaving like a Derived1
object to behaving like a Derived2 object, that's not (generally speaking)
possible, because Derived1 and Derived2 are not related.

However, you can create an instance of a Derived1 class and assign it to a
pointer-to-Base class variable (a Base*), and it will then behave as a
Derived1 object. (but you'll want to be sure that the Base class destructor
and the foo() function are both virtual). Then you can delete that
instance, and create a new one based on Derived2 and it will behave as a
Derived2 object.

Like this:

Base* mode = new Derived1();
mode->foo(); // calls Derived1::foo
delete mode;
mode = new Derived2();
mode->foo(); // calls Derived2::foo
delete mode;

But you can't create an object of type Derived1 and "switch it" to behave
like a Derived2 object. There's simply no mechanism for that which is safe
and reliable. Casting is "possible", but it is not guaranteed to work. For
example:

Base* mode = new Base();
(Derived1*)mode->foo();
(Derived2*)mode->foo();

This may work. It may blow up horrendously. And, it may work for you but
fail for others! You just can't say for sure, because you have not created
instances of Derived1 and Derived2...you are just lying to the compiler and
telling it that you have!


-Howard
 

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

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top