Re: Confused about non-virtual functions

Discussion in 'C++' started by Victor Bazarov, Jun 24, 2003.

  1. "Robert William Vesterman" <> wrote...
    > 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(),


    OK, here is your first mistake. If the function is non-virtual,
    nothing can _override_ it. Any member of the derived class with
    the same name _hides_ it.

    > 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.


    No. Any non-virtual function call is resolved at compile time.
    If object of type E is passed where a reference, say, to B is
    expected, no object E exists inside, only the B part of E is
    passed in:

    void foo(B& rb)
    {
    // Here there is no 'E'. There is only 'B'
    rb.f();
    }

    void bar()
    {
    E e;
    foo(e); // 'e' is converted to 'B&'.
    }

    > 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?


    Non-static functions are bound (resolved) at compile time. It
    speeds up the process (no need to look it up using sime kind of
    virtual function mechanism), and absence of virtual functions
    usually means smaller objects. Leaner, meaner.

    Having a member function that has the same (or similar) type
    in two classes can be a requirement from the design point of
    view. Let's take a very simple example: to be able to sort
    a collection of objects of type T using standard means, the T
    needs to have operator < defined (if no special comparison
    function is provided). To use two different classes (whether
    related or not) in some generic algorithm that requires the use
    of some function 'f()', the two classes have to both implement
    that function. You may have only one version of it, in the
    base class of the two, and let the derived one use it, or you
    may need to redefine it just because it has to use some data
    members in that class. The function doesn't have to be virtual
    because due to the intention it will never be called through
    polymorphic means.

    > 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".


    Non-virtual functions cannot be overridden. Please print that
    statement out on a sheet of paper and hang above your monitor.

    > That is, imagine a language C++--, which is identical to C++ except
    > that non-virtual functions cannot be overridden.


    Why imagine anything? In C++ non-virtual functions cannot be
    overridden.

    > What's an example of
    > a case where C++ is more useful, or nicer, or cleaner, or safer, or
    > more whatever, than C++--?


    Learn the language. It's useful, nice, clean, safe, as it is.

    Victor
    Victor Bazarov, Jun 24, 2003
    #1
    1. Advertising

  2. Great, great, great. Thank you for the semantics lesson. Please
    allow me to rephrase my question:

    Please give me an example of why it is useful that C++ allows the
    following:

    class Base
    {
    void func ( void );
    };

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

    Thank you.

    Bob Vesterman.
    Robert William Vesterman, Jun 24, 2003
    #2
    1. Advertising

  3. "Robert William Vesterman" <> wrote...
    > Great, great, great. Thank you for the semantics lesson. Please
    > allow me to rephrase my question:
    >
    > Please give me an example of why it is useful that C++ allows the
    > following:
    >
    > class Base
    > {
    > void func ( void );
    > };
    >
    > class Derived : public Base
    > {
    > void func ( void );
    > };


    template<class T> void callClassSpecificFunc(T& t)
    {
    t.func();
    }

    int main()
    {
    Base b;
    Derived d;
    callClassSpecificFunc(b);
    callClassSpecificFunc(d);
    }


    Now, you give me an example how it would be beneficial to disallow
    that.

    Victor
    Victor Bazarov, Jun 24, 2003
    #3
  4. Victor Bazarov

    Cy Edmunds Guest

    "Robert William Vesterman" <> wrote in message
    news:...
    > Great, great, great. Thank you for the semantics lesson. Please
    > allow me to rephrase my question:
    >
    > Please give me an example of why it is useful that C++ allows the
    > following:
    >
    > class Base
    > {
    > void func ( void );
    > };
    >
    > class Derived : public Base
    > {
    > void func ( void );
    > };
    >
    > Thank you.
    >
    > Bob Vesterman.


    Well, that's an interesting point. It isn't something I would do with code I
    wrote myself. But if Base was part of a library I was using it might turn
    out to be a useful workaround.

    I think the real reason for non-virtual functions is to avoid the overhead
    of a virtual function call.
    Cy Edmunds, Jun 24, 2003
    #4
  5. "Cy Edmunds" <> wrote...
    > "Robert William Vesterman" <> wrote in message
    > news:...
    > > Great, great, great. Thank you for the semantics lesson. Please
    > > allow me to rephrase my question:
    > >
    > > Please give me an example of why it is useful that C++ allows the
    > > following:
    > >
    > > class Base
    > > {
    > > void func ( void );
    > > };
    > >
    > > class Derived : public Base
    > > {
    > > void func ( void );
    > > };
    > >
    > > Thank you.
    > >
    > > Bob Vesterman.

    >
    > Well, that's an interesting point. It isn't something I would do with code

    I
    > wrote myself. But if Base was part of a library I was using it might turn
    > out to be a useful workaround.
    >
    > I think the real reason for non-virtual functions is to avoid the overhead
    > of a virtual function call.


    The reason for non-virtual functions is just because they exist. The
    reason for _virtual_ functions is to implement polymorphism. People
    tried to do away with non-virtual functions. What good did it do?
    Nothing. Slow code and weird problems with calling virtual functions
    for objects that haven't even begun constructing... Can you guess the
    name of the language?

    Victor
    Victor Bazarov, Jun 24, 2003
    #5
  6. On Tue, 24 Jun 2003 01:44:44 GMT, "Victor Bazarov"
    <> wrote:

    >"Robert William Vesterman" <> wrote...
    >> Great, great, great. Thank you for the semantics lesson. Please
    >> allow me to rephrase my question:
    >>
    >> Please give me an example of why it is useful that C++ allows the
    >> following:
    >>
    >> class Base
    >> {
    >> void func ( void );
    >> };
    >>
    >> class Derived : public Base
    >> {
    >> void func ( void );
    >> };

    >
    >template<class T> void callClassSpecificFunc(T& t)
    >{
    > t.func();
    >}
    >
    >int main()
    >{
    > Base b;
    > Derived d;
    > callClassSpecificFunc(b);
    > callClassSpecificFunc(d);
    >}


    I'm sorry, I'm not seeing what you mean. How does the fact that
    func() is not virtual figure into the use, or lack thereof, of the
    above construct?

    Thanks,

    Bob Vesterman.
    Robert William Vesterman, Jun 24, 2003
    #6
  7. "Robert William Vesterman" <> wrote...
    > On Tue, 24 Jun 2003 01:44:44 GMT, "Victor Bazarov"
    > <> wrote:
    >
    > >"Robert William Vesterman" <> wrote...
    > >> Great, great, great. Thank you for the semantics lesson. Please
    > >> allow me to rephrase my question:
    > >>
    > >> Please give me an example of why it is useful that C++ allows the
    > >> following:
    > >>
    > >> class Base
    > >> {
    > >> void func ( void );
    > >> };
    > >>
    > >> class Derived : public Base
    > >> {
    > >> void func ( void );
    > >> };

    > >
    > >template<class T> void callClassSpecificFunc(T& t)
    > >{
    > > t.func();
    > >}
    > >
    > >int main()
    > >{
    > > Base b;
    > > Derived d;
    > > callClassSpecificFunc(b);
    > > callClassSpecificFunc(d);
    > >}

    >
    > I'm sorry, I'm not seeing what you mean. How does the fact that
    > func() is not virtual figure into the use, or lack thereof, of the
    > above construct?


    It doesn't. That's the beauty of it. And, BTW, what the hell does
    virtuality have to do with it? Didn't you say in your other posting
    that you didn't want to compare them to virtual functions?

    In the given example the fact that 'Derived' is derived from 'Base'
    has no relevance. Two classes each has a function named 'func' with
    a certain signature. Why should the language prohibit that? Please
    abstract from "virtual" and get a simple fact: inheritance shouldn't
    have any bearing on whether the language allows or prohibits to have
    the same type function in two classes.

    struct B { void f(); }; // OK?
    struct D { void f(); }; // unrelated. Still OK?
    struct DB : B { void f(); }; // related. Why not OK?

    For the users of those classes there is no need to know whether DB
    and B are related or not. Whenever 'f' is called, it will be the
    right 'f'.

    Victor
    Victor Bazarov, Jun 24, 2003
    #7
  8. Victor Bazarov

    David White Guest

    Victor Bazarov <> wrote in message
    news:ELPJa.5710$XG4.4416@rwcrnsc53...
    > In the given example the fact that 'Derived' is derived from 'Base'
    > has no relevance. Two classes each has a function named 'func' with
    > a certain signature. Why should the language prohibit that?


    Perhaps because it's asking for trouble. I don't know about prohibit, but at
    least warn.

    Derived d;
    Base *pb = &d;
    Derived *pd = &d;
    pb->f();
    pd->f();

    I don't think anyone would expect the two calls above to call different
    functions.

    David
    David White, Jun 24, 2003
    #8
  9. David White wrote:
    >
    > Victor Bazarov <> wrote in message
    > news:ELPJa.5710$XG4.4416@rwcrnsc53...
    > > In the given example the fact that 'Derived' is derived from 'Base'
    > > has no relevance. Two classes each has a function named 'func' with
    > > a certain signature. Why should the language prohibit that?

    >
    > Perhaps because it's asking for trouble. I don't know about prohibit, but at
    > least warn.
    >
    > Derived d;
    > Base *pb = &d;
    > Derived *pd = &d;
    > pb->f();
    > pd->f();
    >
    > I don't think anyone would expect the two calls above to call different
    > functions.


    Please. Speak only for yourself. If my current situation asks for
    calling different functions, then this is exactly what I expect
    and this is exactly why I don't make that function virtual.


    --
    Karl Heinz Buchegger
    Karl Heinz Buchegger, Jun 24, 2003
    #9
  10. Victor Bazarov wrote:
    >
    >
    > The reason for non-virtual functions is just because they exist. The
    > reason for _virtual_ functions is to implement polymorphism. People
    > tried to do away with non-virtual functions. What good did it do?
    > Nothing. Slow code and weird problems with calling virtual functions
    > for objects that haven't even begun constructing... Can you guess the
    > name of the language?
    >


    Hmm. I guess I first need a cup of coffee :)


    --
    Karl Heinz Buchegger
    Karl Heinz Buchegger, Jun 24, 2003
    #10
  11. Victor Bazarov

    David White Guest

    "Karl Heinz Buchegger" <> wrote in message
    news:...
    >
    >
    > David White wrote:
    > > Perhaps because it's asking for trouble. I don't know about prohibit,

    but at
    > > least warn.
    > >
    > > Derived d;
    > > Base *pb = &d;
    > > Derived *pd = &d;
    > > pb->f();
    > > pd->f();
    > >
    > > I don't think anyone would expect the two calls above to call different
    > > functions.

    >
    > Please. Speak only for yourself. If my current situation asks for
    > calling different functions, then this is exactly what I expect
    > and this is exactly why I don't make that function virtual.


    Then I'm sure glad I don't have to maintain any of your code.

    David
    David White, Jun 24, 2003
    #11
  12. Victor Bazarov

    David White Guest

    "Rob Williscroft" <> wrote in message
    news:Xns93A468B77B747ukcoREMOVEfreenetrtw@195.129.110.131...
    > David White wrote in news:xGRJa.7685$:
    > >
    > > Perhaps because it's asking for trouble. I don't know about prohibit,
    > > but at least warn.
    > >
    > > Derived d;
    > > Base *pb = &d;
    > > Derived *pd = &d;
    > > pb->f();
    > > pd->f();
    > >
    > > I don't think anyone would expect the two calls above to call
    > > different functions.
    > >

    >
    > The function call's have different signatures, maybe they resolve
    > (after conversion's) to the same function, maybe they don't.
    >
    > In some header:
    >
    > void func(Base *b);
    >
    > In a possibly diffrent header:
    >
    > void func(Derived *d);
    >
    > In a xource file:
    >
    > Derived d;
    > Base *pb = &d;
    > Derived *pd = &d;
    >
    > func(pb);
    > func(pd);
    >
    > It's called overloading and its a feature of the language.


    Yes, I know.


    > If you really must call the same function for both objects you can:
    >
    > func(static_cast<Base *>(pb));
    > func(static_cast<Base *>(pd));
    >
    > Or from your example:
    >
    > pb->Base::f();
    > pd->Base::f();
    >
    > This is actually better than my example as it avoids casts!
    > You can also select the overload with a cast:
    >
    > // call func(static_cast<Base *>(pd));
    > static_cast< void (*)(Base *) >(func)(pd);
    >
    > In real code you should avoid the casts and you *should*
    > expect the code that is executed by *any* expresion to be
    > dependant on the *static-types* involved.


    This isn't relevant to the thread. We are talking about _overriding_ and the
    presence/absence of the 'virtual' keyword. Overloading is a different matter

    David
    David White, Jun 24, 2003
    #12
  13. On 24 Jun 2003, you wrote in comp.lang.c++:

    > "Rob Williscroft" <> wrote in message
    > news:Xns93A468B77B747ukcoREMOVEfreenetrtw@195.129.110.131...
    >> David White wrote in news:xGRJa.7685$:
    >> >
    >> > Perhaps because it's asking for trouble. I don't know about
    >> > prohibit, but at least warn.
    >> >
    >> > Derived d;
    >> > Base *pb = &d;
    >> > Derived *pd = &d;
    >> > pb->f();
    >> > pd->f();
    >> >
    >> > I don't think anyone would expect the two calls above to call
    >> > different functions.
    >> >

    >>

    >
    > This isn't relevant to the thread. We are talking about _overriding_
    > and the presence/absence of the 'virtual' keyword. Overloading is a
    > different matter


    Your quite right overloading doesn't have anything to do with it,
    it was a distraction.

    void unexpected(A *a, B *b)
    {
    a->func();
    b->func();
    }

    There are several possiblities to confound the expecatation's
    above:

    1) b->func() actually calls A::func().
    2) a->func() actually calls B::func().
    3) a->func() or b->func() or both call C::func() or D::func()...
    4) multiple combination's of the above.

    About the only thing expected that could happen is that:
    a->func() actually calls A::func() and b->func() actually calls
    B::func().

    Apparently we need a warning for that ?

    Rob.
    --
    http://www.victim-prime.dsl.pipex.com/
    Rob Williscroft, Jun 24, 2003
    #13
  14. Karl Heinz Buchegger wrote:
    >
    > Victor Bazarov wrote:
    > >
    > >
    > > The reason for non-virtual functions is just because they exist. The
    > > reason for _virtual_ functions is to implement polymorphism. People
    > > tried to do away with non-virtual functions. What good did it do?
    > > Nothing. Slow code and weird problems with calling virtual functions
    > > for objects that haven't even begun constructing... Can you guess the
    > > name of the language?
    > >

    >
    > Hmm. I guess I first need a cup of coffee :)


    Bazarov is on crack. That's clear. Braindamaged "polymorphic" C++'s
    vf/dc/ti behavior for objects under construction and destruction aside
    for a moment [you'd need something ala 'poly'/'non-poly' qualifiers...
    and poly_cast to do it 'right'), you, my friend Karl, should better
    learn about so called 'final' (and 'sealed') methods, to begin with.
    Well, the following might help, I hope:

    http://www.jaggersoft.com/csharp_standard/17.5.4.htm
    http://www.jaggersoft.com/csharp_standard/17.5.5.htm
    http://java.sun.com/docs/books/jls/second_edition/html/classes.doc.html#11246

    regards,
    alexander.
    Alexander Terekhov, Jun 24, 2003
    #14
  15. "Robert William Vesterman" <> wrote...
    > On Tue, 24 Jun 2003 03:41:24 GMT, "Victor Bazarov"
    > <> wrote:
    >
    > >"Robert William Vesterman" <> wrote...
    > >> On Tue, 24 Jun 2003 01:44:44 GMT, "Victor Bazarov"
    > >> <> wrote:
    > >>
    > >> >"Robert William Vesterman" <> wrote...
    > >> >> Great, great, great. Thank you for the semantics lesson. Please
    > >> >> allow me to rephrase my question:
    > >> >>
    > >> >> Please give me an example of why it is useful that C++ allows the
    > >> >> following:
    > >> >>
    > >> >> class Base
    > >> >> {
    > >> >> void func ( void );
    > >> >> };
    > >> >>
    > >> >> class Derived : public Base
    > >> >> {
    > >> >> void func ( void );
    > >> >> };
    > >> >
    > >> >template<class T> void callClassSpecificFunc(T& t)
    > >> >{
    > >> > t.func();
    > >> >}
    > >> >
    > >> >int main()
    > >> >{
    > >> > Base b;
    > >> > Derived d;
    > >> > callClassSpecificFunc(b);
    > >> > callClassSpecificFunc(d);
    > >> >}
    > >>
    > >> I'm sorry, I'm not seeing what you mean. How does the fact that
    > >> func() is not virtual figure into the use, or lack thereof, of the
    > >> above construct?

    > >
    > >It doesn't. That's the beauty of it. And, BTW, what the hell does
    > >virtuality have to do with it? Didn't you say in your other posting
    > >that you didn't want to compare them to virtual functions?

    >
    > I guess I'm not getting my question across.


    I guees you aren't.

    > >In the given example the fact that 'Derived' is derived from 'Base'
    > >has no relevance. Two classes each has a function named 'func' with
    > >a certain signature. Why should the language prohibit that? Please
    > >abstract from "virtual" and get a simple fact: inheritance shouldn't
    > >have any bearing on whether the language allows or prohibits to have
    > >the same type function in two classes.
    > >
    > > struct B { void f(); }; // OK?
    > > struct D { void f(); }; // unrelated. Still OK?
    > > struct DB : B { void f(); }; // related. Why not OK?
    > >
    > >For the users of those classes there is no need to know whether DB
    > >and B are related or not. Whenever 'f' is called, it will be the
    > >right 'f'.

    >
    > Really?


    Really.

    > Am I not correct in thinking that two different f()s will be called on
    > the same instance of a DB if you refer to it as a DB and if you refer
    > to it as a B?


    What do you mean by "if you refer to it as a B"? Since DB derives
    from B, it contains a B in it as a subobject. When you take a DB&,
    say, and convert it to B&, you essentially "extract" the subobject
    B out of DB to manipulate. If you then call 'f' for B&, WHY should
    it call anything but B::f? It's the B object [inside DB object].

    > So you're saying that in either case, that's "the right 'f'"?


    Yes.

    > Even
    > though they're two different f's?


    Yes.

    > Really?


    Really.

    > I'm not disagreeing that it
    > would be "the syntactically correct 'f' given the rules of C++" - I'm
    > just saying... really?


    REALLY.

    > You think that's "right"?


    Yes, I think that's right (and no quotes).

    > That's the feature that I'm asking for an actual, useful example of.


    I guess I am not getting my examples across.

    Victor
    Victor Bazarov, Jun 24, 2003
    #15
  16. Victor Bazarov

    David White Guest

    Victor Bazarov <> wrote in message
    news:...
    > "David White" <> wrote...
    > > Derived d;
    > > Base *pb = &d;
    > > Derived *pd = &d;
    > > pb->f();
    > > pd->f();
    > >
    > > I don't think anyone would expect the two calls above to call different
    > > functions.

    >
    > Anyone who doesn't know C++, probably.


    So, you come across this routinely then?

    David
    David White, Jun 25, 2003
    #16
  17. Thank you, Victor; your responses have given genuine insight into the
    human condition.

    Bob Vesterman.
    Robert William Vesterman, Jun 25, 2003
    #17
  18. Robert William Vesterman wrote:
    > Thank you, Victor; your responses have given genuine insight into the
    > human condition.
    >
    > Bob Vesterman.


    Huh? I thought they gave genuine insight into C++...

    --
    --- remove zees if contacting via email ---
    John M. Gabriele, Jun 26, 2003
    #18
  19. Robert William Vesterman <> wrote in message news:<>...
    [snip]
    > So you're saying that in either case, that's "the right 'f'"? Even
    > though they're two different f's? Really? I'm not disagreeing that it
    > would be "the syntactically correct 'f' given the rules of C++" - I'm
    > just saying... really? You think that's "right"?
    >
    > That's the feature that I'm asking for an actual, useful example of.


    operator=

    Here are some references why this should not be made virtual.
    http://groups.google.com/groups?hl=&rnum=10
    http://groups.google.com/groups?q=v...lm=&rnum=7
    http://groups.google.com/groups?q=v...UTF-8&selm=8ggq8o$dak$&rnum=2

    Dave
    David Cattarin, Jun 27, 2003
    #19
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. David White
    Replies:
    11
    Views:
    3,638
    Alexander Terekhov
    Jun 27, 2003
  2. tom_usenet
    Replies:
    0
    Views:
    853
    tom_usenet
    Jun 24, 2003
  3. David Cattarin
    Replies:
    0
    Views:
    765
    David Cattarin
    Jun 24, 2003
  4. Michael Winter
    Replies:
    9
    Views:
    600
    Michael Winter
    Sep 24, 2003
  5. John Goche
    Replies:
    10
    Views:
    716
    Marcus Kwok
    Dec 8, 2006
Loading...

Share This Page