Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Re: Confused about non-virtual functions

Reply
Thread Tools

Re: Confused about non-virtual functions

 
 
David White
Guest
Posts: n/a
 
      06-24-2003
Robert William Vesterman <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> I'm confused about the purpose of non-virtual functions. As I
> understand it, if you have a class E that extends a class B and
> overrides a non-virtual function f(), then the f() that actually gets
> called for an E object depends upon whether that E object is known as
> an E or as a B at the time of the call.


Here 'known as' means the declared type where the call is made, I take it.

Non-virtual functions are overwhelmingly those that are not overridden at
all. Their purpose is to do something that is not for overriding. Virtual
function calls require indirection, for which there is likely to be a
performance penalty, a penalty that is unnecessary if the function is not to
be overridden.

> I don't understand what's useful about this ambiguity in what the f()
> of an E is. Could someone please give me an example of why it would
> be useful?


I can't think of one. I can't think of a circumstance in which I would
override a non-virtual function.

> I don't mean "useful as opposed to virtual functions". I mean "useful
> as opposed to not allowing non-virtual functions to be overridden in
> the first place".


I would suggest that a compiler issue a warning, at least, whenever a
non-virtual function is overridden.

David



 
Reply With Quote
 
 
 
 
Karl Heinz Buchegger
Guest
Posts: n/a
 
      06-24-2003


David White wrote:
>
> Robert William Vesterman <(E-Mail Removed)> wrote in message
> news:(E-Mail Removed)...
> > I'm confused about the purpose of non-virtual functions. As I
> > understand it, if you have a class E that extends a class B and
> > overrides a non-virtual function f(), then the f() that actually gets
> > called for an E object depends upon whether that E object is known as
> > an E or as a B at the time of the call.

>
> Here 'known as' means the declared type where the call is made, I take it.
>
> Non-virtual functions are overwhelmingly those that are not overridden at
> all. Their purpose is to do something that is not for overriding. Virtual
> function calls require indirection, for which there is likely to be a
> performance penalty, a penalty that is unnecessary if the function is not to
> be overridden.
>
> > I don't understand what's useful about this ambiguity in what the f()
> > of an E is. Could someone please give me an example of why it would
> > be useful?

>
> I can't think of one. I can't think of a circumstance in which I would
> override a non-virtual function.
>


Very simple.
Imagine you have a class: Base
This class has member functions. In order to simplify things you decide
to factor out the common code and create a helper function for that:

class Base
{
void foo() { ...; Helper(); ... }
void foo2() { ...; Helper(); ... }

void Helper();
};

Now you derive a class from Base: Derived
It does the same thing: It has some functions and in order to
simplify things you factor out common code and put it into an Helper
function - which by accident gets the very same name as the
one in the base class.

class Derived : public Base
{
void foo3() { ...; Helper(); ... }
void foo4() { ...; Helper(); ... }

void Helper();
}

Now: If the correct job for Base::foo() and Base::foo2() is to use
Base::Helper() then you would be very surprised if Derived::Helper()
is called. If on the other hand the correct job for Base::foo()
and Base::foo2() is to use the Helper() from the most derived
class, then you declare Helper() as being virtual and be happy
with using polymorphism to do the job.

--
Karl Heinz Buchegger
http://www.velocityreviews.com/forums/(E-Mail Removed)
 
Reply With Quote
 
 
 
 
David White
Guest
Posts: n/a
 
      06-24-2003
"Karl Heinz Buchegger" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
>
>
> David White wrote:
> >
> > I can't think of one. I can't think of a circumstance in which I would
> > override a non-virtual function.
> >

>
> Very simple.
> Imagine you have a class: Base
> This class has member functions. In order to simplify things you decide
> to factor out the common code and create a helper function for that:
>
> class Base
> {
> void foo() { ...; Helper(); ... }
> void foo2() { ...; Helper(); ... }
>
> void Helper();
> };
>
> Now you derive a class from Base: Derived
> It does the same thing: It has some functions and in order to
> simplify things you factor out common code and put it into an Helper
> function - which by accident gets the very same name as the
> one in the base class.
>
> class Derived : public Base
> {
> void foo3() { ...; Helper(); ... }
> void foo4() { ...; Helper(); ... }
>
> void Helper();
> }
>
> Now: If the correct job for Base::foo() and Base::foo2() is to use
> Base::Helper() then you would be very surprised if Derived::Helper()
> is called. If on the other hand the correct job for Base::foo()
> and Base::foo2() is to use the Helper() from the most derived
> class, then you declare Helper() as being virtual and be happy
> with using polymorphism to do the job.


Well, I wouldn't do it. It's confusing and it's asking for trouble. Someone
not so familiar with the code might notice 'Helper' in the derived class's
interface, and later see the calls to 'Helper' in the base class function
bodies and assume that it's a virtual call. You might have the completely
wrong understanding of what's happening simply because you failed to notice
that there is no 'virtual' on the base-class declaration of 'Helper'().
Sorry, but I think this is ghastly.

David



 
Reply With Quote
 
Karl Heinz Buchegger
Guest
Posts: n/a
 
      06-24-2003


David White wrote:
>
>
> Well, I wouldn't do it.


If you are working with a class framework you might do it
without even noticing that you do it.

> It's confusing and it's asking for trouble. Someone
> not so familiar with the code might notice 'Helper' in the derived class's
> interface, and later see the calls to 'Helper' in the base class function
> bodies and assume that it's a virtual call. You might have the completely
> wrong understanding of what's happening simply because you failed to notice
> that there is no 'virtual' on the base-class declaration of 'Helper'().


If one analyzes code that sloppy he/she should stop
immediatly using C++

--
Karl Heinz Buchegger
(E-Mail Removed)
 
Reply With Quote
 
Alexander Terekhov
Guest
Posts: n/a
 
      06-24-2003

David White wrote:
>
> David White <(E-Mail Removed)> wrote in message
> news:BuNJa.7667$(E-Mail Removed)...
>
> [all snipped]
>
> In light of Victor's post, interpret 'overridden' and 'override' in my post
> more loosely than usual. By 'override' I meant adding a function of the same
> name with matching arguments in a derived class. Of course, Victor is right
> that if you do this to a non-virtual function then you are not really
> overriding it.


This is called 'hiding'... 'scoping', you know.

regards,
alexander.
 
Reply With Quote
 
David White
Guest
Posts: n/a
 
      06-24-2003
Karl Heinz Buchegger <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
>
>
> David White wrote:
> >
> >
> > Well, I wouldn't do it.

>
> If you are working with a class framework you might do it
> without even noticing that you do it.


More grounds for the compiler giving a warning.

> > It's confusing and it's asking for trouble. Someone
> > not so familiar with the code might notice 'Helper' in the derived

class's
> > interface, and later see the calls to 'Helper' in the base class

function
> > bodies and assume that it's a virtual call. You might have the

completely
> > wrong understanding of what's happening simply because you failed to

notice
> > that there is no 'virtual' on the base-class declaration of 'Helper'().

>
> If one analyzes code that sloppy he/she should stop
> immediatly using C++


I disagree. In real code I've never seen the same function in a derived
class that hadn't been declared 'virtual' in the base class. I've never
heard of the practice written about, or recommended anywhere. I don't
believe it's a common practice. If you can convince me otherwise then I'll
change my mind. If this practice is so rare that few programmers would
expect to come across it, then misunderstandings are likely. To call it
"sloppy", as though anyone who isn't perfect at all times shouldn't be
programming is just bullshit. Mistakes happen. If they didn't then all
software would be bug-free. I just think that using a practice that few
would expect, and which isn't necessary, is going to make mistakes more
likely. But, as I said, if you can convince me that I'm wrong about the
frequency of this practice then I'll change my mind.

David






 
Reply With Quote
 
Karl Heinz Buchegger
Guest
Posts: n/a
 
      06-25-2003


David White wrote:
>
> >
> > If one analyzes code that sloppy he/she should stop
> > immediatly using C++

>
> I disagree. In real code I've never seen the same function in a derived
> class that hadn't been declared 'virtual' in the base class.


It is used sometimes for private/protected helper functions when
refactoring code. Most of the time it simply happens without the
programmer even noticing it.

> I've never
> heard of the practice written about, or recommended anywhere. I don't
> believe it's a common practice. If you can convince me otherwise then I'll
> change my mind. If this practice is so rare that few programmers would
> expect to come across it, then misunderstandings are likely. To call it
> "sloppy", as though anyone who isn't perfect at all times shouldn't be
> programming is just bullshit.


I haven't said that anyone who isn't perfect should stop programming.
I said: anyone who wines around not noticing that a function is
virtual should stop.

> Mistakes happen.



You don't have to tell me.
Nevertheless: Doing a code analyze based on assumptions (which is
ok) and then figuring out that the assumptions didn't hold
and blaming the language for that ....

And yes, I have done lots of foreign code analyzes. Figuring out
what was virtual and what was not, has never been a problem.

> If they didn't then all
> software would be bug-free. I just think that using a practice that few
> would expect, and which isn't necessary, is going to make mistakes more
> likely. But, as I said, if you can convince me that I'm wrong about the
> frequency of this practice then I'll change my mind.
>
> David


--
Karl Heinz Buchegger
(E-Mail Removed)
 
Reply With Quote
 
David White
Guest
Posts: n/a
 
      06-26-2003
Robert Groves <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> On Tue, 24 Jun 2003 20:23:17 +1000, "David White" <no.email@provided>
> wrote:
> >Well, I wouldn't do it. It's confusing and it's asking for trouble.

Someone
> >not so familiar with the code might notice 'Helper' in the derived

class's
> >interface, and later see the calls to 'Helper' in the base class function
> >bodies and assume that it's a virtual call. You might have the completely
> >wrong understanding of what's happening simply because you failed to

notice
> >that there is no 'virtual' on the base-class declaration of 'Helper'().
> >Sorry, but I think this is ghastly.
> >


> Of course thats what you think, you're a java or maybe c-sharp
> programmer. The point is that this is normal in C++.


Never written one character of Java or C#. I wouldn't touch C# with a barge
pole, simply because it's a Microsoft proprietary language.

In chronological order, the languages I've used are: a Basic-like language,
assembler, C, C++. I've been using C++ for about 8 years, always in OO
designs, and I disagree with you that "this is normal in C++". In my
experience - meaning code that I've written, my colleagues have written, and
examples in books and magazines - I am yet to come across non-virtual usage
of identical functions in base and derived classes. Maybe I'm too sheltered,
but that's my experience.

pBase = pDerived;
pBase->func();
pDerived->func();

If you find that, say, 99.9% of the time a function call through an object
pointer calls the same function, regardless of which class the pointer is
declared to point to (i.e., the function is virtual), then when you see such
calls in code you are naturally going to expect them to be virtual calls.

Also, I just find it instinctively objectionable that a _different_ function
will be called depending on whether you declare the _same_ object as a Base*
or Derived*. I just find it too subtle and contrary to the promise of
polymorphic behaviour in an OO design that what happens when you call a
particular function (or, in OO terms, send a particular message) depends on
what type you _declare_ an object to be, rather than what type the object
_is_.

David



 
Reply With Quote
 
Victor Bazarov
Guest
Posts: n/a
 
      06-26-2003
"David White" <(E-Mail Removed)> wrote...
> [...]
> Also, I just find it instinctively objectionable that a _different_

function
> will be called depending on whether you declare the _same_ object as a

Base*
> or Derived*. [...]


You've been writing C++ for "about 8 years" and still cannot
understand one simple thing: it's NOT the same object. Once
you manage to comprehend this, you'll understand why calling
a function with the same name _should_ be different _unless_
it's a virtual function.

To help you understand what it means "not the same object",
please run this:

#include <iostream>

struct A {
double foo;
};

struct B {
int a;
void func() {
std::cout << (void*)this << std::endl;
}
};

struct D : A, B {
void func() {
std::cout << (void*)this << std::endl;
}
};

int main() {
D d;
D *pd = &d;
B *pb = &d;
void *p = pd;
std::cout << "As D : " << p << std::endl;
p = pb;
std::cout << "As B : " << p << std::endl;
pd->func();
pb->func();
}

Does it output the same address? If it doesn't, how can
"the same object" have different addresses?

Think about it before you reply next time.

Victor


 
Reply With Quote
 
David White
Guest
Posts: n/a
 
      06-27-2003
Victor Bazarov <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> "David White" <(E-Mail Removed)> wrote...
> > [...]
> > Also, I just find it instinctively objectionable that a _different_

> function
> > will be called depending on whether you declare the _same_ object as a

> Base*
> > or Derived*. [...]

>
> You've been writing C++ for "about 8 years" and still cannot
> understand one simple thing: it's NOT the same object. Once
> you manage to comprehend this, you'll understand why calling
> a function with the same name _should_ be different _unless_
> it's a virtual function.
>
> To help you understand what it means "not the same object",
> please run this:


My argument was in the context of the example that _I_ gave. Why give a
completely different one?

class Base
{
public:
void func();
//...
};

class Derived : public Base
{
public:
void func();
//...
};

void f()
{
Derived d;
Base *pBase = &d;
Derived *pDerived = &d;
pBase->func();
pDerived->func();
}

Aside from the pointers, how many objects have been created here? One, a
Derived. That's all.

Nevertheless, I'll look at yours.

> #include <iostream>
>
> struct A {
> double foo;
> };
>
> struct B {
> int a;
> void func() {
> std::cout << (void*)this << std::endl;
> }
> };
>
> struct D : A, B {
> void func() {
> std::cout << (void*)this << std::endl;
> }
> };
>
> int main() {
> D d;


Only one object here, a D.

> D *pd = &d;


Points to the D part of d, which of course includes the A and B parts, which
it inherits.

> B *pb = &d;


Points to the B part of d, which might or might not have the same address as
the D part. In any case, we are still pointing to a D, because that's the
type that d is.

> void *p = pd;


Converts the address of d to void*, with who-knows what result.

> std::cout << "As D : " << p << std::endl;
> p = pb;
> std::cout << "As B : " << p << std::endl;
> pd->func();
> pb->func();
> }
>
> Does it output the same address? If it doesn't, how can
> "the same object" have different addresses?


Because you are pointing to different parts of the _same_ object. So what?

David



 
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
please help me in distinguish redefining functions, overloading functions and overriding functions. Xiangliang Meng C++ 1 06-21-2004 03:11 AM
Virtual functions and virtual base classes - I'm confused Michael Winter C++ 9 09-23-2003 11:17 PM
Re: Confused about non-virtual functions Victor Bazarov C++ 18 06-27-2003 03:18 PM
Re: Confused about non-virtual functions David Cattarin C++ 0 06-24-2003 01:51 PM
Re: Confused about non-virtual functions tom_usenet C++ 0 06-24-2003 12:14 PM



Advertisments