Archived

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

John Dowis

Virtual?

Recommended Posts

First of all, since this is my first post here I want to say thanks to the people who run this site. I am a senior CS major, and I''ve been wondering when I was going to learn the REAL stuff. Good thing I happened to come here. I read the reviews on Andre LaMothe''s "Tricks of the Windows Game Programming Gurus", and on their advice I decided to buy it... in three days I have learned more on programing than the last three years of college. In particular, his explanation of Windows32 programming helped me greatly, as I knew nothing about it from school. However, I had a question on something I am reading that I don''t understand. He uses a lot of C, whereas I am entirely trained (in the order I learned them) in Basic, Pascal, C++, Ada, VC++. I don''t know a lot of the old C stlye commands, so I guess it is making it hard to understand some of LaMothe''s code (although, as the people here said, he is very good at explaining his code). One part I don''t understand is: virtual void _stdcall fx(void) = 0; The main problems I am having with this are the parts "virtual", "_stdcall", and I am also wondering why he put "void" as a parameter to the function "fx" (at least it appears that way), and then why (or how he even can) set it equal to anything, in this case 0. Thanks in advance for any help, I greatly appreciate it. -John Dowis

Share this post


Link to post
Share on other sites
As far as I know the keyword ''virtual'' is only part of c++, so I don''t know what that''s about.

_stdcall is a calling convention, it''s used to determine how arquements are passed to a function, _stdcall is used in windows programs alot, usualy as a macro such as WINAPI, CALLBACK and the like.

The void, in C, tells the compiler that there are no arguements to the function. Otherwise, any number of of them can be passed without an error.

Share this post


Link to post
Share on other sites
quote:
Original post by John Dowis

virtual void _stdcall fx(void) = 0;




Thats definitely not C. If it is C++, then that means it is a pure virtual member function . Look it up in your favourite C++ book, or if you're lucky some other forum goer will tell you all about polymorphism. I would, but i think a book (or someone else) would do a better job explaining it than i could.

[edited by - sark on January 19, 2003 12:58:33 AM]

Share this post


Link to post
Share on other sites
Virtual means that say you had a code like this:
class cPlayer{\\Class player
void punch();Function punch within class player
}player1;
cplayer public:cKnight{\\derived class from cplayer
virtual void punch(); \\Now instead of using the punch
\\From cPlayer it uses the new punch from
\\cKnight which is different
This will probably help if you know about derived classes but if not sorry I''m tired of thinking



Favorite Quotes:
Gandalf: You shall not pass.
Smeagol: My Precccious!
Smeagol: My little hobbitses
Can you tell i''m a lotr fan!!!
I hope so.

Share this post


Link to post
Share on other sites
quote:
Original post by SSJCORY
Virtual means that say you had a code like this:
class cPlayer{\\Class player
void punch();Function punch within class player
}player1;
cplayer public:cKnight{\\derived class from cplayer
virtual void punch(); \\Now instead of using the punch
\\From cPlayer it uses the new punch from
\\cKnight which is different
This will probably help if you know about derived classes but if not sorry I'm tired of thinking



On second thoughts, maybe there are people who could explain polymorphism worse than i could...

[edited by - sark on January 20, 2003 3:21:02 AM]

Share this post


Link to post
Share on other sites
quote:
Original post by sark
On second thoughts, maybe there are people who could explain polymorphism worse than i could...

...LOL...



Update GameDev.net system time campaign: ''date ddmmHHMMYYYY''

Share this post


Link to post
Share on other sites
quote:
Original post by John Dowis
Is _stdcall and WINAPI the same thing?



According to windef.h, amidst an ugly assortment of #ifdef''s, is:

#define WINAPI __stdcall

Share this post


Link to post
Share on other sites

class SomeClass
{
public:
virtual int GetClassType(){return 1;}
};

class Class1 : public SomeClass
{
public:
int GetClassType(){return 10;}
};

class Class2 : public SomeClass
{
public:
int GetClassType(){return 100;}
};

SomeClass Instance_SomeClass;
Class1 Instance_Class1;
Class2 Instance_Class2;

int Var1 = Instance_SomeClass.GetClassType(); // Var1 will be "1"
int Var2 = Instance_Class1.GetClassType(); // Var2 will be "10"
int Var3 = Instance_Class2.GetClassType(); // Var3 will be "100"

I'm not very familiar with class inheritance but I hope this will help
you get started...

[Edit] Fixed a very little thing in the classes.


KaMiKaZe

[edited by - Kamikaze15 on January 20, 2003 8:40:24 AM]

Share this post


Link to post
Share on other sites
quote:
Original post by John Dowis
One part I don''t understand is:

virtual void _stdcall fx(void) = 0;

The main problems I am having with this are the parts "virtual"

virtual is a C++ keyword to indicate which functions will be despatched dynamically. If a function is virtual, it means that the actual function which gets called is determined at runtime, according to the dynamic type of the object receiving the function call. For example, if you have this simple hierarchy:

  
class B
{
public:
virtual void foo() { /* ... */ }
};

class D : public B
{
public:
void foo() { /* ... */
}
};

Public inheritance of B indicates that you can use a D wherever a B is expected, since D implements a superset of B''s behaviour.

Then, say you have this code:

B *b1 = new B;
B *b2 = new D; // a B is expected, but create a D

b1->foo();
b2->foo();

Since foo is marked as virtual, it will get despatched based on the dynamic type of the object. The dynamic type is what appeared on the right-hand side of the new expression. So, for b1->foo(), B::foo gets called and, for b2->foo(), D::foo gets called. This is a limited form of polymorphism, known as "subtype polymorphism".
quote:

"_stdcall"

When a function gets called, there are many ways of passing parameters. Pretend you have this function signature:

int foo(int x, int y);

Where do the x and y get their values from? How does the callsite know how to retrieve the return value? You might push y onto the stack, followed by x, and then have foo pop them back off. Or you might push x followed by y. You might put them into registers, or indirect via a memory location. There are many permutations of how you might do this, and "stdcall" denotes one way of doing it. Check out your compiler''s documentation to find out more.
quote:

I am also wondering why he put "void" as a parameter to the function "fx"

Because he''s into C habits. It''s not necessary in C++.
quote:

why (or how he even can) set it equal to anything, in this case 0.

That confusing syntax is not an assignment. If a function declaration in a class is followed by "=0", it means the function is "pure virtual". Pure virtual means "any classes which inherit me *must* implement this function if they are to be instantiated". If an implementation of the function is not provided, then an attempt to create an instance will fail, i.e. the class is "abstract".

BTW, this is all basic C++, not C. I suggest that you ask whoever "entirely trained you in C++" for your money back.

Share this post


Link to post
Share on other sites
quote:
Original post by Kamikaze15
[...] I''m not very familiar with class inheritance but I hope this will help you get started...

What exactly are you trying to demonstrate? It''s not how virtual works, that''s for sure. All of your function calls are fixed-up at compile-time.

Share this post


Link to post
Share on other sites
By using dynamic despetching is that slower then what kamikazee suggested? Since the compiler knows during compililation time on what function to use it can be optimized when compiled but the method you showed us it is determined at runtime.

Share this post


Link to post
Share on other sites
quote:
Original post by ph33r
By using dynamic despetching is that slower then what kamikazee suggested?

Whether something is "slower" only makes sense if the two features being compared achieve the same ends. Static despatching is obviously different to dynamic despatching, so you should not make a direct comparison. If you have to despatch a function based on the dynamic type of an object, you simply cannot use static despatch; you have to pay for dynamic despatch whichever way you look at it. Kamikaze15''s example was completely irrelevant to John Dowis''s questions.
quote:

Since the compiler knows during compililation time on what function to use it can be optimized when compiled but the method you showed us it is determined at runtime.

Yes. Usually, it will be indirected via a pointer to the vtable. However, if you don''t want dynamic despatch then you shouldn''t use it. It just so happens that "virtual" competes with inheritance for the "most commonly misused feature of C++" crown.

Share this post


Link to post
Share on other sites
quote:
virtual" competes with inheritance for the "most commonly misused feature of C++" crown


Hate to pester you - but can you please expand on that? Why is virtual the most misused feature of c++? I am using virtual functions in my game currently via dynamic despatching and I'm hoping I'm not using it incorrectly

error: 500

[edited by - ph33r on January 20, 2003 10:18:45 AM]

Share this post


Link to post
Share on other sites
quote:
Original post by ph33r
Hate to pester you - but can you please expand on that? Why is virtual the most misused feature of c++?

Because people often mark functions as virtual "just in case". Instead of being decisive, they say "well, someone might want to inherit from this class, so I''ll make the functions virtual", and then they go on to make *everything* virtual. Take a look at the C++ Standard Library for various examples of how you should implement classes. E.g. how many virtual functions does std::basic_string have?

Share this post


Link to post
Share on other sites
Right I can understand that and to further testify to your point in a few books I've read it even said "as a general rule if you ever might plan on using a derived class that will overload those functions make them virtual" so I can see how many people mark many functions as virtual, but whats the big deal?

Like you said if the function is virtual and they don't use dynamic despatching then it will be decided during compile time what function it calls and there will be no slow down in speed. So making a function virtual "in case" has no real effect that I can tell.

[edited by - ph33r on January 20, 2003 10:50:29 AM]

Share this post


Link to post
Share on other sites
quote:
Opss, sorry for my bad reply, I''m not very familiar with virtual stuff too...

Kamikaze15 don''t feal bad - John Dowis showed a lack of understanding of any type use of virtual functions so your example wasn''t that inappropriate

Share this post


Link to post
Share on other sites
quote:
Original post by ph33r
I can see how many people mark many functions as virtual, but whats the big deal?

There''s two (potential) problems. Firstly, if a function doesn''t need to be virtual, then it''s unnecessary overhead to make it virtual. It *will* get dynamically resolved in some circumstances, and it can bump up the size of the class. That''s sometimes an issue for the legions of premature optimisers who so love C++, and is what leads to people whining about the inefficiency of virtual functions. The second problem is that it may be indicative of sloppy thinking. Many abstract data types do not need any virtual functions, so what thinking lies behind making the functions virtual?
quote:

Kamikaze15 don''t feal bad - John Dowis showed a lack of understanding of any type use of virtual functions so your example wasn''t that inappropriate

It was inappropriate because it doesn''t show any use of virtual functions. Remove virtual from the example and it does the same thing. However, the point isn''t to make Kamikaze feel bad, or to discourage him from trying to help, just to point out to possibly confused readers that it doesn''t demonstrate what they might think.

Share this post


Link to post
Share on other sites
quote:
Original post by ph33r
So making a function virtual "in case" has no real effect that I can tell.

A base class'' invariant behaviour, the behaviour which is part of the generalisation of its derived classes, should not be made up of virtual functions. When you make a function virtual you are specifically stating that the details of how the function fulfils its task may differ in derived classes. If this is not the case, then the function does not make sense if it is declared virtual. There should be no "in case".
quote:
Original post by SabreMan
they say "well, someone might want to inherit from this class, so I''ll make the functions virtual"

One of Meyers'' points, IMO, applies to unnecessarily pondering whether you may need to derive from your class. "Make non-leaf classes abstract." That means that you should only ever instantiate objects from the most derived classes. All base classes should be abstract. So if you think you may need to derive from your class later than it''s destined to be a generalisation. It changed my perspective on a few things. But I''m unsure of how much people follow that rule and how important it is. I, personally, really like the theory behind it.

Share this post


Link to post
Share on other sites
Yikes, this thread exploded overnight. I went to the bookstore last night and bought C++: The Complete Reference, fourth edition. Answered my question, but damn, LaMothe still uses some funny stuff in his code that not even that book has reference to. But, when I look at it long enough, I (usually) figure it out.

Thanks for all the help guys.

-John Dowis

Share this post


Link to post
Share on other sites
Sabreman(or anyone else who knows),
You once told me this
quote:

The rule for destructors is more complicated than what you say, and here it is: if you plan to delete a derived class via a pointer to base, then the base class must have a virtual dtor. Memorize it now, worry about why later.



I feal confident now that I understand polymorphism but I would like to know the why now.

error: 500x1

Share this post


Link to post
Share on other sites
quote:
Original post by Whoknewb
Sabreman(or anyone else who knows),
You once told me this

quote:
Original post by Sabreman
The rule for destructors is more complicated than what you say, and here it is: if you plan to delete a derived class via a pointer to base, then the base class must have a virtual dtor. Memorize it now, worry about why later.


quote:
Original post by Whoknewb
I feal confident now that I understand polymorphism but I would like to know the why now.


In order to destroy a derived class object, the derived class destructor must be called, then the parent base class' destructor must be called, then the next base class' destructor must be called and so on up the inheritance hierachy. If you do not declare your base class destructors virtual, then the call is made statically. If you have a derived class object being treated as a base class object and delete it without the destructor being virtual, then the destructor which gets called will have been resolved at compile time as the base class destructor. This is not the destructor which you want called. By declaring the base class destructor as virtual, you allow the call to be resolved at runtime and everything will work correctly with the other destructors up the inheritance hierachy being called as required. I'm not clued up on the C++ standard, but Meyers says that deleting an object which you are treating polymorphically will result in undefined behaviour.


[edited by - NotAnAnonymousPoster on January 20, 2003 6:26:56 PM]

Share this post


Link to post
Share on other sites
quote:
Original post by NotAnAnonymousPoster
In order to destroy a derived class object

Aside: the term "class object" has a well established meaning in various languages which makes it''s usage in this context confusing. Just "object" will do.
quote:

If you have a derived class object being treated as a base class object and delete it without the destructor being virtual, then the destructor which gets called will have been resolved at compile time as the base class destructor.

That''s not what the C++ Standard specifies. All it says is that, if you delete a derived via a pointer to base, the resultant behaviour is undefined. A non-virtual dtor is then used as an obscure idiom for indicating a class was not designed with derivation in mind. However, it *is* OK (technically) to derive from a class with a non-virtual dtor, if it will not be deleted via a pointer to its base.

Share this post


Link to post
Share on other sites