Topic: Virtual function overheads


Author: Tony Simons <ajhs@dcs.shef.ac.uk>
Date: 1997/12/18
Raw View
Hi,

I'd love an answer to the following question.  Are virtual functions
bound statically when they are invoked through an object rather than
through a pointer?

This is more interesting than you might expect:  Strostrup '91 only
provides for static invocation if the fully-qualified name of the
virtual function is used, viz:

 MyClass::vfunc();  // bound statically

inside some other member function of MyClass.  However, my question
applies to normal invocation cases, viz:

 obj.vfunc();

I can think of reasons why the answer should be both yes and no.  On
the "yes" side:

An instance of any class derived from MyClass will be sliced and
truncated when it is assigned to a MyClass variable, such that there
would be no point in attempting to apply a redefined version of
vfunc(), since this might erroneously attempt to manipulate additional
data members introduced by the derived class.  In practice, the version
of vfunc() defined for the base MyClass is invoked.  This might as well
be statically bound, but is it?

On the "no" side:

When obj.vfunc() is processed, obj is bound to *this by reference and
all virtual function invocations through pointers or references are
subject to dynamic binding.  The slicing operation replaces the type
tag of the derived instance with the type tag of the base instance.
The vtable is still accessed and the base class version of vfunc() is
invoked through dynamic binding.  This is naturally a waste of effort,
but somehow required by the need to process all virtual invocations in
a consistent way.

I truly hope that the answer is "yes", since this would allow the
design of class libraries in which virtual functions are only bound
dynamically in those contexts which truly require this; however, I
suspect that the answer may be "no".  Could respondents please reply
to me by email:

 A.Simons@dcs.shef.ac.uk

since I'm a fairly infrequent new-group reader.

Many thanks,

Tony.
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: Alex Jonas <ajonas@zip.com.au>
Date: 1997/12/19
Raw View
Tony Simons wrote:

> Hi,
>
> I'd love an answer to the following question.  Are virtual functions
> bound statically when they are invoked through an object rather than
> through a pointer?
>

Yes, they are statically bound. See 12.2.6 'To get polymorphic behaviour in
C++...'
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: Gerhard Huebner <ghuebner@lrt.mw.tu-muenchen.de>
Date: 1997/12/19
Raw View
> I'd love an answer to the following question.  Are virtual functions
> bound statically when they are invoked through an object rather than
> through a pointer?
>
> This is more interesting than you might expect:  Strostrup '91 only
> provides for static invocation if the fully-qualified name of the
> virtual function is used, viz:
>
>         MyClass::vfunc();               // bound statically
>
> inside some other member function of MyClass.  However, my question
> applies to normal invocation cases, viz:
>
>         obj.vfunc();
>

If you call virtual functions of an object whose exact class is known at
compile-time, the function is bound statically or even (!) expanded inline.

Example:

class A {
public:
    virtual void doit() = 0;
};

class B : public A {
public:
    virtual void doit() { ... } // declared & defined inline
};

class C : public A {
public:
    virtual void doit(); // not inline
};

void C::doit { ... }

...

B b;
b.doit();  // B::doit is expanded in-line
C c;
c.doit(); // C::doit is bound statically here
A *ab = &b, *ac = &c;
ab->doit(); // Exact class of ab not known => dynamically bound
ac->doit(); // Exact class of ac not known => dynamically bound

Hope, that helps.

Also take a look at the C++ FAQ lite!!!

http://www.cerfnet.com/~mpcline/c++-faq-lite/

Regards,

--
Dipl.-Phys. Gerhard Huebner        __
Institute of Astronautics          \ \____   "Not a plucky hero
--------------------------------===>--____>   until one reaches
Technische Universitaet Muenchen   /_/        the Great Wall"
Tel.: +49-89-289-16015, Fax: 16004
http://www.lrt.mw.tu-muenchen.de/personen/ghuebner/ghuebner.html
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: stephen.clamage_nospam@eng.sun.com (Steve Clamage)
Date: 1997/12/19
Raw View
On 18 Dec 1997 16:40:30 PST, Tony Simons <ajhs@dcs.shef.ac.uk> wrote:

>I'd love an answer to the following question.  Are virtual functions
>bound statically when they are invoked through an object rather than
>through a pointer?

The standard does not require it, but compilers typically do so. It is
only an efficiency question, not a correctness question. A virtual
function is selected according to the dynamic type of the object in
question. If the call is via an object and not via a pointer or
reference, the static and dynamic types are the same, so you get the
same result whether or not the virtual call mechanism is used.

>I can think of reasons why the answer should be both yes and no.  On
>the "yes" side:
>
>An instance of any class derived from MyClass will be sliced and
>truncated when it is assigned to a MyClass variable, such that there
>would be no point in attempting to apply a redefined version of
>vfunc(), ...

That is irrelevant. If the object is sliced from Derived to Base, any
virtual functions invoked are those for a Base object, not a Dervied
object -- the Derived versions could not possibly be invoked, because
the object is not a Derived.

Talking about objects being sliced is perhaps confusing. No object is
ever actually sliced. In C++, objects cannot change type without
invoking undefined behavior. (Unions could possibly be considered an
exception, but members of unions cannot have virtual functions.)
"Slicing an object" really means copying a Derived value to a Base
object. Only the Base part gets copied and the target was and is just
a Base.

---
Steve Clamage, stephen.clamage_nospam@eng.sun.com
( Note: remove "_nospam" when replying )
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: Valentin Bonnard <bonnardv@pratique.fr>
Date: 1997/12/22
Raw View
Tony Simons <ajhs@dcs.shef.ac.uk> writes:

> Are virtual functions
> bound statically when they are invoked through an object rather than
> through a pointer?

All unqualified calls call the function corresponding to
the dynamic type of object, ie the most derived object of
the instance. That's very simple.

Now you might have noticed that the dynamic type of a
declared object rarely changes; precisely, it doesn't
change after its ctor has finished its work and before
the dtor starts:

Bar b;

assert (typeid(b) == typeid(Bar)); // b is a Bar
foo (b);
assert (typeid(b) == typeid(Bar)); // still a Bar

So the dynamic type IS the static type.

> I can think of reasons why the answer should be both yes and no.  On
> the "yes" side:

Well, it is BOTH yes and no, since here the 'no' answer
isn't the opposite of 'yes', but the opposite of
a _different_ question.

> Could respondents please reply
> to me by email:
>
>  A.Simons@dcs.shef.ac.uk
>
> since I'm a fairly infrequent new-group reader.

It's considered not polite/against netiquette to ask
for such a thing. However, I cc this message to you, so
you don't have to wait until is appears in the newsgroup.

--

Valentin Bonnard                mailto:bonnardv@pratique.fr
info about C++/a propos du C++: http://www.pratique.fr/~bonnardv/
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: jodle@bix.com (jodle)
Date: 1997/12/22
Raw View
Steve Clamage (stephen.clamage_nospam@eng.sun.com) wrote:

: Talking about objects being sliced is perhaps confusing. No object is
: ever actually sliced. In C++, objects cannot change type without
: invoking undefined behavior. (Unions could possibly be considered an
: exception, but members of unions cannot have virtual functions.)
: "Slicing an object" really means copying a Derived value to a Base
: object. Only the Base part gets copied and the target was and is just
: a Base.

Perhaps "partial copy" would be a clearer and more accurate term.
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]