Archived

This topic is now archived and is closed to further replies.

lovely virtual functions...

This topic is 5122 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

class oh_a
{
public:
    int a;
    virtual void test(void);
};
void oh_a::test(void)
{
    a=100;
}
class oh_b : public oh_a
{
public:
    int b;
    virtual void test(void);
};
void oh_b::test(void)
{
    b=200;
}
now, how do i define the test function from base class a, since its virtual, we should be able to change what it does, but how?

Share this post


Link to post
Share on other sites
quote:
how do i define the test function from base class a

It''s already defined:

void oh_a::test(void)
{
a=100;
}

quote:
..., since its virtual, we should be able to change what it does, but how?

You have changed what it does.

oh_a* pa = new oh_a();
oh_a* pb = new oh_b();
pa->test(); // calls oh_a::test(), assign 100 to a
pb->test(); // calls oh_b::test(), assign 200 to b

Share this post


Link to post
Share on other sites
so basically, if you have a virtual function that has the same name in two classes, and you inherit from one of those class with opposite class, the new virtual function overrides the original virtual function

correct?

[edited by - fireking on November 30, 2003 7:23:43 AM]

Share this post


Link to post
Share on other sites
what if two classes each had a function of the same name. Lets say the first class uses this function to initialize the array, and lets say the class that is inheriting from first class just sets a variable to false or something. Will the array still be initialized?

(note the functions are not virtual)

Share this post


Link to post
Share on other sites
Well, you should initalize arrays in constructor. Then, when you're inheriting, you should call that inherited constructor in constructor that you supply with new class.

EDIT: sorry for misunderstanding. In that case, function from class B hides function from class A. So, A.func() calls first function, and B.func() calls the second.

[edited by - Koshmaar on November 30, 2003 8:01:59 AM]

Share this post


Link to post
Share on other sites
so how would you implement a creation/deletion system

events such as

OnCreate//called before its created, in case user wants to do something
OnCreated//called after creation
OnDestroy//called before destroying (might wanna save some values!)
OnDestroyed//called after destroyed (update stuff if you like)

since virtual doesnt apply here, because they are overridden as soon as you inherit it (and almost every major class would have these functions)

regular functions dont apply either, unless you can do something like

void myclass:Create(void)
{
OnCreate();
myclass::inheritedclass::OnCreate();
...
}

but thats really unethical, this stuff should happen automatically

i was thinking function pointers, but now that i think about it, how do you call a create function in class a when class b has the same function name (maybe same parameters) and inherits class a...

bleh

Share this post


Link to post
Share on other sites
regular functions dont apply either, unless you can do something like [some code]

someclass::somefunction(); will force the choice of a given version of the function.

but thats really unethical, this stuff should happen automatically

No. If it did happen automatically, what would you do when it''s not appropriate. Overriding base class functions means you replace the original version entirely. If you want to call it in the process, do so explicitely.

Only for constructors and destructors does it make sense to do it automatically.


[ Start Here ! | How To Ask Smart Questions | Recommended C++ Books | C++ FAQ Lite | Function Ptrs | CppTips Archive ]
[ Header Files | File Format Docs | LNK2001 | C++ STL Doc | STLPort | Free C++ IDE | Boost C++ Lib | MSVC6 Lib Fixes ]

Share this post


Link to post
Share on other sites
Use constructors and desttructors :-) For example:

class A
{
public:
A() {foo=1;};

private:
int foo;
};

class B : public A
{
B();
};

B :: B() : A()
{
foo++;
}

Share this post


Link to post
Share on other sites
quote:
Original post by noVum
And foo++; should really be ++foo;


Ah, and C++ should really be called ++C using the same grammar rules, but that's really pedantic (even if it is strictly correct)!

++foo is slightly faster because it just increments, rather then using the current value and then incrementing. Correct me if I'm wrong though.

Cheers,

Paul


[edited by - paulsdsrubbish on November 30, 2003 9:07:57 AM]

Share this post


Link to post
Share on other sites
It''s not faster in this case, but ++foo is what you actually want to do, not foo++
It will give you the same result, but it''s simply bad practice.

Please consult your manual about the difference bettween post and pre increment

Share this post


Link to post
Share on other sites
quote:
Original post by noVum
It's not faster in this case, but ++foo is what you actually want to do, not foo++
It will give you the same result, but it's simply bad practice.

Please consult your manual about the difference bettween post and pre increment


Well it is faster in user types and non-primitives.

Do a google search:
http://www.google.co.uk/search?q=post+and+pre+increment+faster+c%2B%2B&ie=UTF-8&oe=UTF-8&hl=en&btnG=Google+Search&meta=

And you'll come up with proof...
http://bmagic.sourceforge.net/enum.html
http://www.codeguru.com/forum/showthread.php?threadid=261345

for example.

But hey, yeah, it depends on compiler optimisations if it is faster or not when it comes to ints.

Edit:
(Infact Borland has this tip page for performance with it's compiler)
http://bdn.borland.com/article/0,1410,28278,00.html

[edited by - paulsdsrubbish on November 30, 2003 12:23:09 PM]

Share this post


Link to post
Share on other sites
back to the OP''s interest in virtual functions ...

here''s some helpfull info that''s not a rule, but should help you understand better ...

a virtual function is used to allow derived classes to invisibly (FROM THE POINT OF VIEW OF THE CLIENT / USER CODE) implement different behaviors for taloring a logical operation to their internals ... (which you already understood)

HOWEVER, a virtual function is NOT meant to hide the base classes version from the derived class ... in fact, there are many situations where the derived class can and should call the base classes version of the function ...

for example ...

IF you are creating a decorator / drawing framework ... you might have virtual functions like this:


class IScreenObject
{
public:
virtual void Draw(void);
}

class SomeObject
{
public virtual void Draw(void);
}

class DecoratedSomeObject
{
public virtual void Draw(void);
}

void DecoratedSomeObject::Draw(void)
{
SomeObject::Draw();

// then do additional stuff here

}


notice in this example, the derived class explicitly calls the bases function, BUT A CLIENT WOULD NOT ... because that WOULD violate the idea of virtual ... to a client virtual means the latter function "replaces" (aka overides) the first function ... but to the class implementor - all of the functions are available to build the desired behavior with ... you can almost think of it like this - the virtual implementations are somewhat like "protected" functions, in that they will not be exposed to non-derived classes (IF a derived class overides them - but they are available to the internals of the derived classes) ...

also understand, that derived versions of virtual functions do not always call the base versions, it''s simply an available feature for situations where it would be appropriate ...

BUT derived class''s constructors and destructors ALWAYS call a base class''s constructor / destructor ... EVEN a virtual destructor ... he''s special ...

If class A has a virtual function foo, and a virtual destructor, and derived class B implements both as well ... and doesn''t explicitly call class A''s version in either ...

if a client calls foo on a B object, ONLY B::foo() gets called ....

if a client calls the destructor on a B object, B::~B() gets called, and then A::~A() gets called ...

just like there is NO WAY to get into the body of a constructor for B ... like B::B(), without some constructor for A having already been called ... although you CAN PICK WHICH ONE you want to have called, in the initializer list ...

here''s an example of that ...

B::B(int i) : A(i)
{
// stuff here
}

tells the compiler to call a constructor for A which takes and int before executing the body of the constructor for B which takes an int ...

but

B::B(int i)
{
// stuff here
}

STILL calls a constructor for A before the body of B ... it''s just the default constructor for A - since a different one wasn''t specified ...

Share this post


Link to post
Share on other sites
quote:
Original post by paulsdsrubbish
quote:
Original post by noVum
It''s not faster in this case, but ++foo is what you actually want to do, not foo++
It will give you the same result, but it''s simply bad practice.

Please consult your manual about the difference bettween post and pre increment


Well it is faster in user types and non-primitives.

Do a google search:
http://www.google.co.uk/search?q=post+and+pre+increment+faster+c%2B%2B&ie=UTF-8&oe=UTF-8&hl=en&btnG=Google+Search&meta=

And you''ll come up with proof...
http://bmagic.sourceforge.net/enum.html
http://www.codeguru.com/forum/showthread.php?threadid=261345

for example.

But hey, yeah, it depends on compiler optimisations if it is faster or not when it comes to ints.

Edit:
(Infact Borland has this tip page for performance with it''s compiler)
http://bdn.borland.com/article/0,1410,28278,00.html

[edited by - paulsdsrubbish on November 30, 2003 12:23:09 PM]


I said it''s not faster IN THIS CASE. Every modern compiler will optimize this.

Share this post


Link to post
Share on other sites
i guess i was assuming that virtual functions worked much like constructors, being that they call through each level of inheritance, instead of just calling the latest definition of the function (or the overidden function in the class definition)

really thats what im looking for, something that mimics constructors, actually i thought this would be a common concept in engines. You are able to call the function, explicitly, but thats not really what we want here, because that kind of indicates some bad design of the entire engine.

an example of good uses for what is trying to be accomplished:

class some_api_wrapper;
class some_engine : public some_api_wrapper;
class my_game : public some_engine;

my_game calls its on create function

this would call the create function in the engine
the engine would call the create function in the api wrapper.
(i think with constructors, this would happen in the opposite direction)

notice, that im not ONLY talking about a create function, this could apply to several other things, such as OnDraw()

my_game.OnDraw()

would trickle down to the some_api_wrapper.OnDraw() function, even though its been inherited

thats what we''re trying to accomplish, an event system that works on any class, even if its by its self, or inherited in a new class

this concept can be seen in use in engines that use nodes for visible objects in the game. It takes the world (the root node), and traverses through each child, and those children''s children, and so on. Implementing that same thing for every class, would involve creating a node system not only for objects within the game, but for classes as well (which doesnt seem like a good idea to me).

Share this post


Link to post
Share on other sites
quote:
an example of good uses for what is trying to be accomplished:

class some_api_wrapper;
class some_engine : public some_api_wrapper;
class my_game : public some_engine;


No no no. my_game isn''t a some_engine and it''s most certainly not some_api_wrapper. Use composition/delegation. Use public inheritance when you can say that a class IS-A another class and where the derived class will not be forced to break LSP. Private inheritace has its uses (achieving EBCO or using policy classes for instance), but delegation is prefered. A game uses an engine, which in turn uses some api.

quote:
this concept can be seen in use in engines that use nodes for visible objects in the game. It takes the world (the root node), and traverses through each child, and those children''s children, and so on. Implementing that same thing for every class, would involve creating a node system not only for objects within the game, but for classes as well (which doesnt seem like a good idea to me).

Yes, probably by using a list with objects which all defines an OnDraw method, not by inheritance. The tree structure appears because objects are composed out of other objects. A monster, for instance, can have objects such as Weapon and Helmet, which all defines an OnDraw method.

Share this post


Link to post
Share on other sites
It's a question whether the relationship ought to be a IS-A relationship or a HAS-A relationship. Composition represents HAS-A relationships; that is, you create new classes by giving them attributes that are themselves other classes. Example: you could create an CarEngine class and then when you go to create a Car class, you declare a CarEngine as one of the data members because a Car HAS-A CarEngine. That in a nutshell is composition.

Inheritance, on the other hand, represents IS-A relationships; a derived class IS-A version of its base class (but not necessarily vice-versa). An example would be creating a Rectangle class, then creating a Square class that inherits from Rectangle. This would be a logical use of inheritance because a Square IS-A Rectangle. Hope that made sense.

[edited by - MRom on December 5, 2003 12:19:46 AM]

Share this post


Link to post
Share on other sites
quote:
Original post by MRom

Inheritance, on the other hand, represents IS-A relationships; a derived class IS-A version of its base class (but not necessarily vice-versa). An example would be creating a Rectangle class, then creating a Square class that inherits from Rectangle. This would be a logical use of inheritance because a Square IS-A Rectangle. Hope that made sense.




Actually Rectangle-Square is a bad example... There are reasons, but I don't want to dig into the depths (The jist: Square has less functionality than Rectangle ...)

Better example would be: SUV IS-A Type of Vehicle:

Vehicle might, for instance have a: ShiftIntoGear() method, SUV would inherit that, but may extend it by providing a PullTrailer() method, the Vehicle class may also have an Accelerate() method, but the SUV might override that with it's own acceleration rate, which may change when PullTrailer() is called.







http://www.michaelraiford.com
http://www.dpalbum-online.com

[edited by - mraiford on December 5, 2003 12:30:01 AM]

Share this post


Link to post
Share on other sites
MRom, sqare inheriting from rectangle violates the liskov substitution principle. See www.objectmentor.com LSP paper for details. In essence, there is no need for square to inherit SetWidth() and SetHeight() from rect as square sides are of equal length. Furthermore, the rect class places a condition on the rect by saying that after an operation on the rect one or both sides of it will be changed. Square always changes both it sides at once. The violation of this behavior causes problems when you pass a square into a function expecting a rect which internally asserts some condition to be true for rect but now it isn''t for the square.

ISA basically states that derived obj has the same behavior as its parent obj. IS KIND OF means that you are allowed to add more behavior to your child object. Say you had a bird as a parent and then have human as its child obj. Human inherited fly() method but we know that humans don''t fly. You''ve inherited some behavior that you''re not going to use or that is simply illogical. This is a violation of ISA principle. When you publicly inherit you also inherit public interface that you then advertise to the rest of the world.

Do not inherit from an object and then override its method(s) without marking those method(s) virtual in the parent object. If you break this rule then you''re sending wrong messages to the programmers that work with that child object. Advertise your intentions by documentation, in this example by marking members virtual.

There are two inheritances. Interface and implementation inheritance. Hierarchies use implementation inheritance and that has been deprecated in exchange for interface inheritance which is more flexible design wise(also less messy). Composition came about by leveling object hierarchies into components. Composition hides the enclosed object''s interface which is a good thing. This allows you to change the objects without disturbing outside world or clients that use the component. Multiple interface inheritance is ok and preferable over implementation inheritance because you don''t inherit data and implementation which is a pain to keep up straight in MI. Your component could also inherit interface and other components.

The interface inheritance gets rid of switch case statements and it promotes replacable implementation which adds flexibility. One thing that I discovered while coding my app and which Allan Holub teaches is that to have a good OO with less maintanence you should abandon procedural thinking(pulling data out of objects) by telling the object to do something and passing object into it that it can then use to do something with it. You can still pull data out but it should be an object with encapsulated state/behavior and not a built-in-type like a float. You don''t want to change clients when object''s internal representation changes.

Share this post


Link to post
Share on other sites
Sorry for the crap inheritance example, guys. I''m just finishing up a Java course at my high school, and the Square-Rectangle example was the example they used throughout the inheritance chapter. JD, thanks for the extensive insight though. Always nice to learn something new.

Share this post


Link to post
Share on other sites