Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > virtual methods ?

Reply
Thread Tools

virtual methods ?

 
 
Corey Murtagh
Guest
Posts: n/a
 
      06-25-2003
Adie wrote:
> Corey Murtagh wrote:

<snip>
>>
>>The above prints '2'... or should. If it doesn't then something is
>>seriously wrong.

>
> You know, I asked my lecturer about this a while back and she said that
> you had to find the type when extracting the pointer from a container, I
> thought at the time that it was a bit clumsy. She's actually a Java
> programmer and suggested it was easier in Java, kinda fundamentally wrong
> wasn't she.


Yeah, it sounds that way. At the very least her statement was
misleading. She shouldn't be 'teaching' things like this to students
when she either doesn't know what she's talking about, or can't
communicate it correctly.

The only time you need to determine the true class of a polymorphic
object is if you need to access methods which are first defined for that
class. There are cases where this is desirable, which is most of the
reason for dynamic_cast<>(). In a lot of cases though you can avoid it
by designing your base class to provide all the interfaces you need for
your derived classes.

--
Corey Murtagh
The Electric Monk
"Quidquid latine dictum sit, altum viditur!"

 
Reply With Quote
 
 
 
 
Adie
Guest
Posts: n/a
 
      06-25-2003
Corey Murtagh wrote:
>Adie wrote:
>>
>> You know, I asked my lecturer about this a while back and she said that
>> you had to find the type when extracting the pointer from a container, I
>> thought at the time that it was a bit clumsy. She's actually a Java
>> programmer and suggested it was easier in Java, kinda fundamentally wrong
>> wasn't she.

>
>Yeah, it sounds that way. At the very least her statement was
>misleading. She shouldn't be 'teaching' things like this to students
>when she either doesn't know what she's talking about, or can't
>communicate it correctly.


Sadly the coverage of standard C++ was poor, three modules (classes) in
total - the first gave us; void main() for which I promptly wrapped on
the knuckles for using on Usenet, the second offered an intro into GUI
toolkits with X, Athena and Qt whilst the third concentrated on using
Borland CPP Builder libraries/GUI with some UML/Patterns stuff thrown in
for good measure. I suppose they're worried that most people would become
bored with three straight C++ modules, disadvantage being that we didn't
get a good coverage of what are considered the basics.

Oh well, there's always books and Usenet, I'll get there in the end

>The only time you need to determine the true class of a polymorphic
>object is if you need to access methods which are first defined for that
>class. There are cases where this is desirable, which is most of the
>reason for dynamic_cast<>(). In a lot of cases though you can avoid it
>by designing your base class to provide all the interfaces you need for
>your derived classes.


Doesn't that go against the grain of keeping Base classes as lightweight
as possible?
 
Reply With Quote
 
 
 
 
Corey Murtagh
Guest
Posts: n/a
 
      06-25-2003
Adie wrote:

> Corey Murtagh wrote:
>
>>Adie wrote:
>>
>>>You know, I asked my lecturer about this a while back and she said that
>>>you had to find the type when extracting the pointer from a container, I
>>>thought at the time that it was a bit clumsy. She's actually a Java
>>>programmer and suggested it was easier in Java, kinda fundamentally wrong
>>>wasn't she.

>>
>>Yeah, it sounds that way. At the very least her statement was
>>misleading. She shouldn't be 'teaching' things like this to students
>>when she either doesn't know what she's talking about, or can't
>>communicate it correctly.

>
>
> Sadly the coverage of standard C++ was poor, three modules (classes) in
> total - the first gave us; void main() for which I promptly wrapped on
> the knuckles for using on Usenet, the second offered an intro into GUI
> toolkits with X, Athena and Qt whilst the third concentrated on using
> Borland CPP Builder libraries/GUI with some UML/Patterns stuff thrown in
> for good measure. I suppose they're worried that most people would become
> bored with three straight C++ modules, disadvantage being that we didn't
> get a good coverage of what are considered the basics.


Unfortunately this seems to be a common trend. The perception that C++
is "too difficult" compared to languages like Java and Visual Basic has
really damaged the educational possibilities.

> Oh well, there's always books and Usenet, I'll get there in the end


As a self-taught programmer I've picked up an aweful lot of useful stuff
online :>

The downside is that I don't have a piece of paper to tell prospective
employers that I'm able to do what I've *been* doing for the past 7
years. Makes it rather difficult to get work, even though they claim
we've got a shortage of C++ programmers over here at the moment.

>>The only time you need to determine the true class of a polymorphic
>>object is if you need to access methods which are first defined for that
>>class. There are cases where this is desirable, which is most of the
>>reason for dynamic_cast<>(). In a lot of cases though you can avoid it
>>by designing your base class to provide all the interfaces you need for
>>your derived classes.

>
> Doesn't that go against the grain of keeping Base classes as lightweight
> as possible?


Code-wise, not really. Your base class doesn't actually have to
implement *any* of those interfaces if you really want it to stay light.
All of the functionality can be implemented down the inheritence tree.

That said, this is a fairly common structure in some areas:

class base_object
{
public:
base_object();
virtual ~base_object();

// some interfaces common to all derived
//...
};

class derived1a : public base_object
{
public:
derived1();
virtual ~derived1();

// common interfaces implemented in this class
//...

// new interfaces implemented for this branch
//...
};

class derived1b : public base_object
{
// like derived1a, but with different new interfaces
};

etc. This allows you to store all of your derived objects in a
base_object pointer, or vector of pointers, or whatever. Each branch
then has to be identified at its branch point using dynamic_cast<>().
So if I have a vector full of base_object*s and I need an interface
that's only provided by objects descended from derived1b, I can filter
the vector with dynamic_cast<>().

It has its uses. It can simplify certain aspects of your programs, but
overuse can make your code that much more difficult to read. Usually
it's preferable to have a more complete interface in the base and
provide implementation details in the descendants.


--
Corey Murtagh
The Electric Monk
"Quidquid latine dictum sit, altum viditur!"

 
Reply With Quote
 
Robert Groves
Guest
Posts: n/a
 
      06-26-2003
On Wed, 25 Jun 2003 18:32:17 +0100, Adie <>
wrote:

>Corey Murtagh wrote:
>>Adie wrote:
>>> Michael Isenman wrote:

>><snip>
>>>>The smart-ass (but mostly correct answer) is "why do you care?". After all,
>>>>if you designed your class
>>>>hierarchy correctly, the polymorphic behavior will occur via virtual
>>>>functions without your knowing the
>>>>type of the object.In you example above, presumably you would just call f(),
>>>>and the correct f() will just
>>>>be called without your having to worry about which type of derived class it
>>>>is.
>>>
>>> So if the for loop looks like;
>>>
>>> for (int i = 0; i < vBase.size(); i++)
>>> {
>>> Base* newBase;
>>> newBase = vBase[i];
>>> newBase->f();
>>> }
>>>
>>> it'll wade through the vector assigning to the Base pointer but will still
>>> call the correct f() for derived object? Is that right? Sounds kinda
>>> groovy if it is.

>>
>>Yes, that's exactly what the 'virtual' keyword is intended for. To test:
>>
>>-----------
>>#include <iostream>
>>
>>class Base
>>{
>>public:
>> virtual int f() const { return 1; }
>>};
>>
>>class Derived : public Base
>>{
>>public:
>> virtual int f() const { return 2; }
>>};
>>
>>int main()
>>{
>>Base* b = new Derived;
>> std::cout << b->f() << std::endl;
>> return 0;
>>}
>>-----------
>>
>>The above prints '2'... or should. If it doesn't then something is
>>seriously wrong.

>
>You know, I asked my lecturer about this a while back and she said that
>you had to find the type when extracting the pointer from a container, I
>thought at the time that it was a bit clumsy. She's actually a Java
>programmer and suggested it was easier in Java, kinda fundamentally wrong
>wasn't she.


If she was a java programmer it is probably because in java there are
no templates. All the standard containers store Objects, which is
basically a Base type for every other java type. So when using a
container you must cast all objects that you pull out of the container
before you can use them. This is a huge flaw in java and, as I
understand, version 1.5 will have some type of templates. So it was
probably her way of doing things coming from java, but in C++ you
don't need to do this, provided you use a template container with the
interface you plan on using.
 
Reply With Quote
 
Thomas Tutone
Guest
Posts: n/a
 
      06-26-2003

"Adie" <> wrote in message
news:...
> >> This is where i'm confused. How do I get the type of object each

pointer
> >> in vBase is pointing to?

> >
> >The smart-ass (but mostly correct answer) is "why do you care?". After

all,
> >if you designed your class
> >hierarchy correctly, the polymorphic behavior will occur via virtual
> >functions without your knowing the
> >type of the object.In you example above, presumably you would just call

f(),
> >and the correct f() will just
> >be called without your having to worry about which type of derived class

it
> >is.

>
> So if the for loop looks like;
>
> for (int i = 0; i < vBase.size(); i++)
> {
> Base* newBase;
> newBase = vBase[i];
> newBase->f();


I know I'm stating the obvious, but I'd substitute:
vBase[i]->f();
for the above three lines. Less typing, plus it gets rid of the unneeded
newBase variable.

> }
>
> it'll wade through the vector assigning to the Base pointer but will still
> call the correct f() for derived object? Is that right? Sounds kinda

groovy
> if it is.


Welcome to C++, my friend.

Best regards,

Tom




 
Reply With Quote
 
Adie
Guest
Posts: n/a
 
      06-26-2003
Adie wrote:

>Heh there's a UK university doing an MSc .NET, there's nothing like a well
>rounded education, and that's nothing like a well a well rounded
>education...


For the record it's ".NET MSc in Distributed Systems Development"

http://www2.dcs.hull.ac.uk/NETMSc/index.html
 
Reply With Quote
 
Karl Heinz Buchegger
Guest
Posts: n/a
 
      06-26-2003


Adie wrote:
>
> >etc. This allows you to store all of your derived objects in a
> >base_object pointer, or vector of pointers, or whatever. Each branch
> >then has to be identified at its branch point using dynamic_cast<>().
> >So if I have a vector full of base_object*s and I need an interface
> >that's only provided by objects descended from derived1b, I can filter
> >the vector with dynamic_cast<>().

>
> Sorry to be dense, but doesn't dynamic_cast<type id>(expression) just cast
> expression to type id? Can you us it in an "if" statement?


The trick with dynamic_cast ist the following:
dynamic_cast also checks if the object you want to cast is really
of the type you specify in the dynamic_cast. If you use it with
pointers and the object is not of the required type you will
get a 0 Pointer. And that is something you can detect.

example:

for (int i = 0; i < vBase.size(); i++)
{
Base* newBase;
newBase = vBase[i];

// now newBase could point to a Base object or to
// DerivedA or DerivedB objects. Figure out which one

// try to cast newBase to a DerivedA pointer.
// But at runtime it should be checked, if the object newBase
// points at is really a DerivedA

DerivedA* pPtrA = dynamic_cast< DerivedA* >( newBase );
if( pPtrA != 0 ) {
// it was a DerivedA object
}

else {
DerivedB* pPtr = dynamic_cast< DerivedB* >( newBase );
if( pPtr != 0 ) {
// it was a DerivedB object
}
else {
// must have been a Base object
}
}
}

Now compare that with the simple use of a virtual function

Additionally. Imagine you introduce a new class in about half a year:

class DerivedC : public Base
{
...
};

What do you have to do? Well, in the above you have to add some logic
for the new class to detect it and add another if - else branch.

And with the dispatch through virtual functions?
Surprise: You have to do nothing! You just implement the function f()
in the new class and the code you already had:

for (int i = 0; i < vBase.size(); i++)
{
Base* newBase;
newBase = vBase[i];
newBase->f();
}

dispatches to DerivedC::f() whenver there is a pointer to DerivedC
stored in the container. You don't even have to recompile the above
loop!


> >It has its uses. It can simplify certain aspects of your programs, but
> >overuse can make your code that much more difficult to read. Usually
> >it's preferable to have a more complete interface in the base and
> >provide implementation details in the descendants.

>
> Might delegation also be used for this kind of problem, wrap the class
> with the added functionality?


Since the goal is to store pointers in a container and use
polymorphism, this is not a good idea. If you want to make
use of polymorphism to your advantage, then creating a complete
interface in the base class is often far less work then any other
option.

--
Karl Heinz Buchegger

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Is there a way to find the class methods of a class, just like'methods' finds the instance methods? Kenneth McDonald Ruby 5 09-26-2008 03:09 PM
Top-Up Methods - Finarea (Voipcheap, internetcalls, etc.) et. al., VOIP Services Question - Top-up Methods News Reader UK VOIP 0 04-10-2006 02:41 PM
Why Petshop Changed all static methods to instance methods when upgrading from version 3.0 to version 3.1? Neo ASP .Net 1 01-07-2005 01:46 AM
virtual methods, virtual bases bug<?> in G++ 3.3 Jim Fischer C++ 3 07-31-2003 08:28 PM
Re: Templates and friends and template methods with private methods. Buster Copley C++ 5 07-07-2003 12:50 AM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57