• We should now be fully online following an overnight outage. Apologies for any inconvenience, we do not expect there to be any further issues.

C++ noob question

irishScott

Lifer
Oct 10, 2006
21,562
3
0
So I've got a project for my CISC 181 class. Without going into details, it revolves around OOP. Here's the problem.

How do I access a subclass method from a superclass pointer?

In my case, I have a general class WarPlane, of which Fighter is a subclass with some different attributes. However, there is a virtual function "compare" in WarPlane that is overloaded in Fighter. However, the overloaded function in Fighter compares data specific to the Fighter class, even though it accepts a WarPlane* as an argument (required by the project).

The function simply compares different attributes specific to its type (or universal attributes in the case of the original WarPlane function)

So I have:

WarPlane* raptor = new Fighter(/*args go here*/);
raptor->compare(/*another WarPlane*/Fighter declared like raptor*/);

Then, I try to compile (gcc) and I get
ERROR: No function getMissile() in class WarPlane

getMissile is a function specific to Fighter used in the compare function.

Thing is, while the object is a WarPlane*, it was created with a Fighter constructor, so it should have the same function set as a fighter right?

2 hours of googleing has yielded nil. Is this simply an impossible scenario, or am I just missing something blatantly obvious here?
 

nickbits

Diamond Member
Mar 10, 2008
4,122
1
81
google these:

dynamic_cast
reinterpret_cast

But this would work too:

void Figher::compare(WarPlane* x)
{
((Fighter*)x)->FighterMethod();
}

But if x wasn't a fighter you'd have a problem. So you must either verify the type of x by your own method or use the run time type information (dynamic_cast).
 

irishScott

Lifer
Oct 10, 2006
21,562
3
0
That did it. Thanks. I'll just add another "type" variable to the class to determine what's what. Thought you couldn't typecast pointers for some reason. :p
 

degibson

Golden Member
Mar 21, 2008
1,389
0
0
You should avoid cases like this where you cast a Superclass* to a Subclass* via (Subclass*), reinterpret_cast, or dynamic_cast in interfaces. If you need a Subclass* in the first place, make your interface require a Subclass* instead of a Superclass*. Are you sure your assignment requires you to take a WarPlane* and then use Fighter-specific data members? It seems like a dubious requirement (can the same thing be accomplished with only WarPlane data members?).
 

Madwand1

Diamond Member
Jan 23, 2006
3,309
0
76
Originally posted by: irishScott
That did it. Thanks. I'll just add another "type" variable to the class to determine what's what. Thought you couldn't typecast pointers for some reason.

A cleaner way to do it would be to use the scope overriding operator on the function -- e.g. p->BaseClass::Foo ();

Adding a variable to represent type isn't generally considered good form -- it's better to avoid it altogether by design where possible, and otherwise to use some of the built-in support. There are some potential arguments about RTTI performance, but the odds are that it isn't critical and as usual, it's better not to optimize too early in this way.
 

irishScott

Lifer
Oct 10, 2006
21,562
3
0
Originally posted by: Madwand1
Originally posted by: irishScott
That did it. Thanks. I'll just add another "type" variable to the class to determine what's what. Thought you couldn't typecast pointers for some reason.

A cleaner way to do it would be to use the scope overriding operator on the function -- e.g. p->BaseClass::Foo ();

Adding a variable to represent type isn't generally considered good form -- it's better to avoid it altogether by design where possible, and otherwise to use some of the built-in support. There are some potential arguments about RTTI performance, but the odds are that it isn't critical and as usual, it's better not to optimize too early in this way.

The project requires an "ID Number" field anyway. I just integrated it into that.
 

irishScott

Lifer
Oct 10, 2006
21,562
3
0
Originally posted by: degibson
You should avoid cases like this where you cast a Superclass* to a Subclass* via (Subclass*), reinterpret_cast, or dynamic_cast in interfaces. If you need a Subclass* in the first place, make your interface require a Subclass* instead of a Superclass*. Are you sure your assignment requires you to take a WarPlane* and then use Fighter-specific data members? It seems like a dubious requirement (can the same thing be accomplished with only WarPlane data members?).

Yes, it's required; and Fighter has it's own private fields (wouldn't really be a point to making a subclass if it didn't) so I can't exclusively use WarPlane*s