Topic: static member functions and 'virtual


Author: AlbertoBarbati@libero.it (Alberto Barbati)
Date: Thu, 20 May 2004 21:10:25 +0000 (UTC)
Raw View
Barry Margolin wrote:
> I think the OP was suggesting that it be based on the way the function
> is named in the call.  If you call base::value(), the internal reference
> to foo() becomes base::foo(); when you call derived::value(), it's
> interpreted as derived::foo().
>
> Virtual static member functions could take a vtable as an extra hidden
> argument in order to implement this.

That's right and might be technically feasible. However, let's dig
deeper and we will found why it comes to a too great cost! Consider the
example if "static virtual" were allowed:

   struct base
   {
     static int value() { return foo(); }
     static virtual int foo() { return 1; }
   };

   struct derived : base
   {
     static virtual int foo() { return 2; }
   };

This might be implemented by having a sort of vtable, and having value()
use that table to perform dispatch. That means value() requires a hidden
parameter to the vtable, so that

base::value() really expands to base::value(base::vtable)

and

derived::value() really expands to base::value(derived::vtable)

But let's step back. value() was not declared virtual, foo() was! That
means that *every* static function would need to be passed an hidden
pointer to the vtable whether they are going to use it or not! That
means two things:

1) there is a cost in this feature even you never use it (but the
philosophy of C++ is that "you shouldn't pay for what you don't use")

2) static functions would no longer be "regular" functions, in the sense
that pointer to a static function would no longer be a
pointer-to-function type. That is unacceptable.

By the way, there is one more reason for not having this feature
provided at the language level and it is that it can be easily obtained
by using standard polymorphism and the singleton pattern.

If you don't like the singleton pattern but you can afford duplication
of code, then templates are the solution. Consider this:

template <class T>
int value()
{
   return T::foo();
}

Then value<base>() returns base::foo() and value<derived>() returns
derived::foo(). No hidden vtables, no virtual dispatch.

Alberto

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: barmar@alum.mit.edu (Barry Margolin)
Date: Fri, 21 May 2004 05:41:34 +0000 (UTC)
Raw View
In article <tf_qc.10700$Wc.389503@twister2.libero.it>,
 AlbertoBarbati@libero.it (Alberto Barbati) wrote:

> Barry Margolin wrote:
> > I think the OP was suggesting that it be based on the way the function
> > is named in the call.  If you call base::value(), the internal reference
> > to foo() becomes base::foo(); when you call derived::value(), it's
> > interpreted as derived::foo().
> >
> > Virtual static member functions could take a vtable as an extra hidden
> > argument in order to implement this.
>
> That's right and might be technically feasible. However, let's dig
> deeper and we will found why it comes to a too great cost! Consider the
> example if "static virtual" were allowed:
>
>    struct base
>    {
>      static int value() { return foo(); }
>      static virtual int foo() { return 1; }
>    };
>
>    struct derived : base
>    {
>      static virtual int foo() { return 2; }
>    };
>
> This might be implemented by having a sort of vtable, and having value()
> use that table to perform dispatch. That means value() requires a hidden
> parameter to the vtable, so that
>
> base::value() really expands to base::value(base::vtable)
>
> and
>
> derived::value() really expands to base::value(derived::vtable)
>
> But let's step back. value() was not declared virtual, foo() was!

Ahh, that's something I missed.  I thought it would be value() that
would be declared virtual.

--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: dave@whipp.name (Dave Whipp)
Date: 23 May 2004 07:40:05 GMT
Raw View
AlbertoBarbati@libero.it (Alberto Barbati) wrote:

> But let's step back. value() was not declared virtual, foo() was! That
> means that *every* static function would need to be passed an hidden
> pointer to the vtable whether they are going to use it or not! That
> means two things:
>
> 1) there is a cost in this feature even you never use it (but the
> philosophy of C++ is that "you shouldn't pay for what you don't use")

You could implement it such that you only pay for it for classes that
actually have "virtual static" functions (or which are derived from
such classes). You'd have to pay for it on all static functions in
those classes though (except the inline ones).

> 2) static functions would no longer be "regular" functions, in the sense
> that pointer to a static function would no longer be a
> pointer-to-function type. That is unacceptable.

This objection does seem resonable, initially, but I think the feature
could be implemented to not have this problem -- if we accept that we
will pay an overhead for classes with "virtual static"s. Assuming
there's no fundamental reason for &derived::non_virtual_static_fn to
be the same value as &base::non_virtual_static_fn, the compiler could
be permitted (required?) to create wrapper functions, which supply the
vtable (meta-class object) to the wrapped implementation.

> By the way, there is one more reason for not having this feature
> provided at the language level and it is that it can be easily obtained
> by using standard polymorphism and the singleton pattern.
>
> If you don't like the singleton pattern but you can afford duplication
> of code, then templates are the solution. [...]:

As with many minor tweaks, I agree that its possible to achieve a
similar effect in many ways -- not having it is definitely not a
show-stopper. But having it in the language does mean that I don't
need to program it inside my application. And getting private/public
visibiilty to work seamlessly with your suggested implementations
might take some thought -- especially if I don't want client programs
(or derived classes) to need to know what I'm doing in the base class.


Dave.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: omni@scient.net ("Jaded Hobo")
Date: Mon, 17 May 2004 17:17:54 +0000 (UTC)
Raw View
Because static members don't require a "this" pointer to be accessed. For a
function to be polymorphics however, the "this" pointer is absolutely
necessary.

"Dave Whipp" <dave@whipp.name> schreef in bericht
news:2d474fd5.0405150816.42a1373d@posting.google.com...
> Consider this code:
>
>   #include <iostream>
>
>   struct base
>   {
>         static int value() { return foo(); }
>         static int foo() { return 1; }
>   };
>
>   struct derived : base
>   {
>         static int foo() { return 2; }
>   };
>
>   int main()
>   {
>         std::cout << base::value() << std::endl;
>         std::cout << derived::value() << std::endl;
>   }
>
>
> Obviously, both base::value() and derived::value() will return the
> same value, because both use base::foo() to get the actual value. Is
> there any reason why the "virtual" keyword cannot be defined to impute
> a polymorthic behavior to static member functions -- so that calling
> derived::value() would use derived::foo()?
>
>
> Dave.
>
> ---
> [ comp.std.c++ is moderated.  To submit articles, try just posting with ]
> [ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
> [              --- Please see the FAQ before posting. ---               ]
> [ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]
>


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: joonyew2@singnet.com.sg ("Joon Yew")
Date: Mon, 17 May 2004 17:18:04 +0000 (UTC)
Raw View
"Dave Whipp" <dave@whipp.name> wrote in message
news:2d474fd5.0405150816.42a1373d@posting.google.com...
> Consider this code:
>
>   #include <iostream>
>
>   struct base
>   {
>         static int value() { return foo(); }
>         static int foo() { return 1; }
>   };
>
>   struct derived : base
>   {
>         static int foo() { return 2; }
>   };
>
>   int main()
>   {
>         std::cout << base::value() << std::endl;
>         std::cout << derived::value() << std::endl;
>   }
>
>
> Obviously, both base::value() and derived::value() will return the
> same value, because both use base::foo() to get the actual value. Is
> there any reason why the "virtual" keyword cannot be defined to impute
> a polymorthic behavior to static member functions -- so that calling
> derived::value() would use derived::foo()?
>

C++ virtual is meant to implement polymorphic behaviour.  Polymorphic
behaviour applies only to operations of object instances.  Polymorphic
behaviour is necessarily invoked through references to object instances of
base classes.

Static member functions are not an object-oriented concept.  So C++ cannot
apply polymorphic behaviour to static member functions.

Cheers
Joon Yew


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: barmar@alum.mit.edu (Barry Margolin)
Date: Mon, 17 May 2004 22:04:17 +0000 (UTC)
Raw View
In article <40a85a01$0$61616$e4fe514c@news.xs4all.nl>,
 omni@scient.net ("Jaded Hobo") wrote:

> Because static members don't require a "this" pointer to be accessed. For a
> function to be polymorphics however, the "this" pointer is absolutely
> necessary.

I think the OP was suggesting that it be based on the way the function
is named in the call.  If you call base::value(), the internal reference
to foo() becomes base::foo(); when you call derived::value(), it's
interpreted as derived::foo().

Virtual static member functions could take a vtable as an extra hidden
argument in order to implement this.

>
> "Dave Whipp" <dave@whipp.name> schreef in bericht
> news:2d474fd5.0405150816.42a1373d@posting.google.com...
> > Consider this code:
> >
> >   #include <iostream>
> >
> >   struct base
> >   {
> >         static int value() { return foo(); }
> >         static int foo() { return 1; }
> >   };
> >
> >   struct derived : base
> >   {
> >         static int foo() { return 2; }
> >   };
> >
> >   int main()
> >   {
> >         std::cout << base::value() << std::endl;
> >         std::cout << derived::value() << std::endl;
> >   }
> >
> >
> > Obviously, both base::value() and derived::value() will return the
> > same value, because both use base::foo() to get the actual value. Is
> > there any reason why the "virtual" keyword cannot be defined to impute
> > a polymorthic behavior to static member functions -- so that calling
> > derived::value() would use derived::foo()?
> >
> >
> > Dave.
> >
> > ---
> > [ comp.std.c++ is moderated.  To submit articles, try just posting with ]
> > [ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
> > [              --- Please see the FAQ before posting. ---               ]
> > [ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]
> >
>
>
> ---
> [ comp.std.c++ is moderated.  To submit articles, try just posting with ]
> [ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
> [              --- Please see the FAQ before posting. ---               ]
> [ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]

--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: dave@whipp.name (Dave Whipp)
Date: Sat, 15 May 2004 17:30:14 +0000 (UTC)
Raw View
Consider this code:

  #include <iostream>

  struct base
  {
        static int value() { return foo(); }
        static int foo() { return 1; }
  };

  struct derived : base
  {
        static int foo() { return 2; }
  };

  int main()
  {
        std::cout << base::value() << std::endl;
        std::cout << derived::value() << std::endl;
  }


Obviously, both base::value() and derived::value() will return the
same value, because both use base::foo() to get the actual value. Is
there any reason why the "virtual" keyword cannot be defined to impute
a polymorthic behavior to static member functions -- so that calling
derived::value() would use derived::foo()?


Dave.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]