C++ static virtual members?
Asked Answered
G

20

186

Is it possible in C++ to have a member function that is both static and virtual? Apparently, there isn't a straightforward way to do it (static virtual member(); is a compile error), but is there at least a way to achieve the same effect?

I.E:

struct Object
{
     struct TypeInformation;

     static virtual const TypeInformation &GetTypeInformation() const;
};

struct SomeObject : public Object
{
     static virtual const TypeInformation &GetTypeInformation() const;
};

It makes sense to use GetTypeInformation() both on an instance (object->GetTypeInformation()) and on a class (SomeObject::GetTypeInformation()), which can be useful for comparisons and vital for templates.

The only ways I can think of involves writing two functions / a function and a constant, per class, or use macros.

Any other solutions?

Gaulin answered 30/11, 2009 at 15:26 Comment(4)
Just a side comment: static methods do not execute on any instance, what means that they do not have the implicit this pointer. That being said, the const in a method signature flags the implicit this pointer as constant and cannot be applied to static methods as they lack the implicit parameter.Caseose
@cvb: I would seriously reconsider replacing your example with code that does not involve reflection. The way it is now you're sort of conflating two separate (albeit related) issues. Yes, and I know it's 5-and-a-half years since you asked it.Finding
One of the feature implicitely required here is to have the compiler checks that each object in a hierarchy implements a specific interface (where one or more of the method is static). Basically, a pure virtual check for static method makes a lot of sense, since if you forget to add the static method, then the compiler should error out. virtual is not the keyword here, it's more abstract which happens to be kind of synonyms in C++, except for this specific case. Unfortunately, you can't do it with C++ currently.Psychoactive
@Gaulin Have you tried using a static interface ? github.com/ilciavo/static_interface_pattern/blob/master/…Arizona
S
94

No, there's no way to do it, since what would happen when you called Object::GetTypeInformation()? It can't know which derived class version to call since there's no object associated with it.

You'll have to make it a non-static virtual function to work properly; if you also want to be able to call a specific derived class's version non-virtually without an object instance, you'll have to provide a second redunduant static non-virtual version as well.

Septum answered 30/11, 2009 at 15:30 Comment(2)
If you think of static class (or classes static members) as a singleton, everything becomes obvious - in your case simply Object::GetTypeInformation should be called - the same way as calling regular virtual method on base class instance. (Of course, if C++ supported virtual static methods)Rockafellow
That's a completely specious argument. If you use the class instead of an object, it would naturally use the version from that class, instead of doing virtual-dispatch. Nothing new there.Scram
D
60

Many say it is not possible, I would go one step further and say it is not meaningfull.

A static member is something that does not relate to any instance, only to the class.

A virtual member is something that does not relate directly to any class, only to an instance.

So a static virtual member would be something that does not relate to any instance or any class.

Deface answered 30/11, 2009 at 15:51 Comment(9)
It is perfectly meaningful in languages where classes are first-class values - e.g. Delphi has that, and also has "static virtual" methods.Gate
Not really - rememeber that in those systems, classes are values themselves, of a single type. At best, their type (class) is derived from a basic 'basetype', and their sibling types would be unions, built-ins, etc. A virtual method is shared across all instances of a single type; thus the virtual methods associated with the "class" type would be shared across all classes.Smyth
Exactly. A "virtual function" is (by definition) a function which is dynamically linked, i.e. it's chosen at runtime depending on the dynamic type of a given object. Hence, no object = no virtual call.Lapsus
I also think that static virtuals are meaningful. It would be possible to define interface classes and include static methods that have to be implemented in derived class.Backsword
It's not so meaningful for a static virtual method, but a static pure virtual method is very meaningful in an interface.Welladvised
It is perfectly meaningful to have a static const string MyClassSillyAdditionalName.Finding
It's completely meaningful, if your intend is to use the compiler to ensure you've implemented a static method in all child class. @BretKuhns is right.Psychoactive
It is meaningful when you need to call child function from parent constructor. https://mcmap.net/q/137348/-c-virtual-function-from-constructor-duplicate/239247Quiberon
it is meaningful for static class factory functions that return null if constructor fails and object if constructor succeeds. This allows us to purge exceptions from the face of the earth since invalid objects are never directly returned to the caller, but checked in between. constructors can't fail, so classes must throw exceptions to shift the problem to programmer, instead of having the static method wrap that exception in no fail, or promiselike/callback shell which is more elegant.Malena
M
26

I ran into this problem the other day: I had some classes full of static methods but I wanted to use inheritance and virtual methods and reduce code repetition. My solution was:

Instead of using static methods, use a singleton with virtual methods.

In other words, each class should contain a static method that you call to get a pointer to a single, shared instance of the class. You can make the true constructors private or protected so that outside code can't misuse it by creating additional instances.

In practice, using a singleton is a lot like using static methods except that you can take advantage of inheritance and virtual methods.

Mintz answered 30/11, 2009 at 15:39 Comment(3)
That's going to cost me performance - unless the compiler can be certain that: 1. It's actually a singleton and 2. Nothing inherits from it, I don't think it can optimize all of the overhead away.Finding
If the performance of this kind of thing worries you then C# is probably the wrong language for you.Mintz
Ah, good point. Obviously it's been a while since I thought about this since I wrote it in 2009. Let me put that another way, then: if this kind of performance thing worries you then maybe you should be avoiding the use of inheritance entirely. The poster specifically asked for virtual methods, so it's strange that you come here to complain about the overhead of virtual methods.Mintz
F
18

It is possible!

But what exactly is possible, let's narrow down. People often want some kind of "static virtual function" because of duplication of code needed for being able to call the same function through static call "SomeDerivedClass::myfunction()" and polymorphic call "base_class_pointer->myfunction()". "Legal" method for allowing such functionality is duplication of function definitions:

class Object
{
public:
    static string getTypeInformationStatic() { return "base class";}
    virtual string getTypeInformation() { return getTypeInformationStatic(); }
}; 
class Foo: public Object
{
public:
    static string getTypeInformationStatic() { return "derived class";}
    virtual string getTypeInformation() { return getTypeInformationStatic(); }
};

What if base class has a great number of static functions and derived class has to override every of them and one forgot to provide a duplicating definition for virtual function. Right, we'll get some strange error during runtime which is hard to track down. Cause duplication of code is a bad thing. The following tries to resolve this problem (and I want to tell beforehand that it is completely type-safe and doesn't contain any black magic like typeid's or dynamic_cast's :)

So, we want to provide only one definition of getTypeInformation() per derived class and it is obvious that it has to be a definition of static function because it is not possible to call "SomeDerivedClass::getTypeInformation()" if getTypeInformation() is virtual. How can we call static function of derived class through pointer to base class? It is not possible with vtable because vtable stores pointers only to virtual functions and since we decided not to use virtual functions, we cannot modify vtable for our benefit. Then, to be able to access static function for derived class through pointer to base class we have to store somehow the type of an object within its base class. One approach is to make base class templatized using "curiously recurring template pattern" but it is not appropriate here and we'll use a technique called "type erasure":

class TypeKeeper
{
public:
    virtual string getTypeInformation() = 0;
};
template<class T>
class TypeKeeperImpl: public TypeKeeper
{
public:
    virtual string getTypeInformation() { return T::getTypeInformationStatic(); }
};

Now we can store the type of an object within base class "Object" with a variable "keeper":

class Object
{
public:
    Object(){}
    boost::scoped_ptr<TypeKeeper> keeper;

    //not virtual
    string getTypeInformation() const 
    { return keeper? keeper->getTypeInformation(): string("base class"); }

};

In a derived class keeper must be initialized during construction:

class Foo: public Object
{
public:
    Foo() { keeper.reset(new TypeKeeperImpl<Foo>()); }
    //note the name of the function
    static string getTypeInformationStatic() 
    { return "class for proving static virtual functions concept"; }
};

Let's add syntactic sugar:

template<class T>
void override_static_functions(T* t)
{ t->keeper.reset(new TypeKeeperImpl<T>()); }
#define OVERRIDE_STATIC_FUNCTIONS override_static_functions(this)

Now declarations of descendants look like:

class Foo: public Object
{
public:
    Foo() { OVERRIDE_STATIC_FUNCTIONS; }
    static string getTypeInformationStatic() 
    { return "class for proving static virtual functions concept"; }
};

class Bar: public Foo
{
public:
    Bar() { OVERRIDE_STATIC_FUNCTIONS; }
    static string getTypeInformationStatic() 
    { return "another class for the same reason"; }
};

usage:

Object* obj = new Foo();
cout << obj->getTypeInformation() << endl;  //calls Foo::getTypeInformationStatic()
obj = new Bar();
cout << obj->getTypeInformation() << endl;  //calls Bar::getTypeInformationStatic()
Foo* foo = new Bar();
cout << foo->getTypeInformation() << endl; //calls Bar::getTypeInformationStatic()
Foo::getTypeInformation(); //compile-time error
Foo::getTypeInformationStatic(); //calls Foo::getTypeInformationStatic()
Bar::getTypeInformationStatic(); //calls Bar::getTypeInformationStatic()

Advantages:

  1. less duplication of code (but we have to call OVERRIDE_STATIC_FUNCTIONS in every constructor)

Disadvantages:

  1. OVERRIDE_STATIC_FUNCTIONS in every constructor
  2. memory and performance overhead
  3. increased complexity

Open issues:

1) there are different names for static and virtual functions how to solve ambiguity here?

class Foo
{
public:
    static void f(bool f=true) { cout << "static";}
    virtual void f() { cout << "virtual";}
};
//somewhere
Foo::f(); //calls static f(), no ambiguity
ptr_to_foo->f(); //ambiguity

2) how to implicitly call OVERRIDE_STATIC_FUNCTIONS inside every constructor?

Foucquet answered 11/5, 2010 at 10:20 Comment(3)
+1 for effort, although I'm not sure this is more elegant than just delegating the functionality to a singleton with virtual methods.Finding
@einpoklum, I can think of a situation when this can be preferable. Suppose we have a lot of client code that already calls static methods. Switching from static methods to a singleton with virtual methods would require changes in client code while the solution presented above is non-invasive.Foucquet
"virtual" keyword is not required for "Foo::getTypeInformation" and "TypeKeeperImpl::getTypeInformation".Sclerophyll
A
18

While Alsk has already given a pretty detailed answer, I'd like to add an alternative, since I think his enhanced implementation is overcomplicated.

We start with an abstract base class, that provides the interface for all the object types:

class Object
{
public:
    virtual char* GetClassName() = 0;
};

Now we need an actual implementation. But to avoid having to write both the static and the virtual methods, we will have our actual object classes inherit the virtual methods. This does obviously only work, if the base class knows how to access the static member function. So we need to use a template and pass the actual objects class name to it:

template<class ObjectType>
class ObjectImpl : public Object
{
public:
    virtual char* GetClassName()
    {
        return ObjectType::GetClassNameStatic();
    }
};

Finally we need to implement our real object(s). Here we only need to implement the static member function, the virtual member functions will be inherited from the ObjectImpl template class, instantiated with the name of the derived class, so it will access it's static members.

class MyObject : public ObjectImpl<MyObject>
{
public:
    static char* GetClassNameStatic()
    {
        return "MyObject";
    }
};

class YourObject : public ObjectImpl<YourObject>
{
public:
    static char* GetClassNameStatic()
    {
        return "YourObject";
    }
};

Let's add some code to test:

char* GetObjectClassName(Object* object)
{
    return object->GetClassName();
}

int main()
{
    MyObject myObject;
    YourObject yourObject;

    printf("%s\n", MyObject::GetClassNameStatic());
    printf("%s\n", myObject.GetClassName());
    printf("%s\n", GetObjectClassName(&myObject));
    printf("%s\n", YourObject::GetClassNameStatic());
    printf("%s\n", yourObject.GetClassName());
    printf("%s\n", GetObjectClassName(&yourObject));

    return 0;
}

Addendum (Jan 12th 2019):

Instead of using the GetClassNameStatic() function, you can also define the the class name as a static member, even "inline", which IIRC works since C++11 (don't get scared by all the modifiers :)):

class MyObject : public ObjectImpl<MyObject>
{
public:
    // Access this from the template class as `ObjectType::s_ClassName` 
    static inline const char* const s_ClassName = "MyObject";

    // ...
};
Audwen answered 15/2, 2015 at 9:10 Comment(0)
M
12

It is possible. Make two functions: static and virtual

struct Object{     
  struct TypeInformation;
  static  const TypeInformation &GetTypeInformationStatic() const 
  { 
      return GetTypeInformationMain1();
  }
  virtual const TypeInformation &GetTypeInformation() const
  { 
      return GetTypeInformationMain1();
  }
protected:
  static const TypeInformation &GetTypeInformationMain1(); // Main function
};

struct SomeObject : public Object {     
  static  const TypeInformation &GetTypeInformationStatic() const 
  { 
      return GetTypeInformationMain2();
  }
  virtual const TypeInformation &GetTypeInformation() const
  { 
      return GetTypeInformationMain2();
  }
protected:
  static const TypeInformation &GetTypeInformationMain2(); // Main function
};
Motto answered 30/11, 2009 at 15:58 Comment(2)
Also, static methods cannot be const. It just does not make sense, what instance are they not going to mutate?Caseose
This is mostly just code duplication. The idea is for the subclasses to only need to have the static const member, not have to have code accessing it.Finding
L
12

It's not possible, but that's just because an omission. It isn't something that "doesn't make sense" as a lot of people seem to claim. To be clear, I'm talking about something like this:

struct Base {
  static virtual void sayMyName() {
    cout << "Base\n";
  }
};

struct Derived : public Base {
  static void sayMyName() override {
    cout << "Derived\n";
  }
};

void foo(Base *b) {
  b->sayMyName();
  Derived::sayMyName(); // Also would work.
}

This is 100% something that could be implemented (it just hasn't), and I'd argue something that is useful.

Consider how normal virtual functions work. Remove the statics and add in some other stuff and we have:

struct Base {
  virtual void sayMyName() {
    cout << "Base\n";
  }
  virtual void foo() {
  }
  int somedata;
};

struct Derived : public Base {
  void sayMyName() override {
    cout << "Derived\n";
  }
};

void foo(Base *b) {
  b->sayMyName();
}

This works fine and basically what happens is the compiler makes two tables, called VTables, and assigns indices to the virtual functions like this

enum Base_Virtual_Functions {
  sayMyName = 0;
  foo = 1;
};

using VTable = void*[];

const VTable Base_VTable = {
  &Base::sayMyName,
  &Base::foo
};

const VTable Derived_VTable = {
  &Derived::sayMyName,
  &Base::foo
};

Next each class with virtual functions is augmented with another field that points to its VTable, so the compiler basically changes them to be like this:

struct Base {
  VTable* vtable;
  virtual void sayMyName() {
    cout << "Base\n";
  }
  virtual void foo() {
  }
  int somedata;
};

struct Derived : public Base {
  VTable* vtable;
  void sayMyName() override {
    cout << "Derived\n";
  }
};

Then what actually happens when you call b->sayMyName()? Basically this:

b->vtable[Base_Virtual_Functions::sayMyName](b);

(The first parameter becomes this.)

Ok fine, so how would it work with static virtual functions? Well what's the difference between static and non-static member functions? The only difference is that the latter get a this pointer.

We can do exactly the same with static virtual functions - just remove the this pointer.

b->vtable[Base_Virtual_Functions::sayMyName]();

This could then support both syntaxes:

b->sayMyName(); // Prints "Base" or "Derived"...
Base::sayMyName(); // Always prints "Base".

So ignore all the naysayers. It does make sense. Why isn't it supported then? I think it's because it has very little benefit and could even be a little confusing.

The only technical advantage over a normal virtual function is that you don't need to pass this to the function but I don't think that would make any measurable difference to performance.

It does mean you don't have a separate static and non-static function for cases when you have an instance, and when you don't have an instance, but also it might be confusing that it's only really "virtual" when you use the instance call.

Landlady answered 5/10, 2018 at 15:8 Comment(0)
W
9

No, this is not possible, because static member functions lack a this pointer. And static members (both functions and variables) are not really class members per-se. They just happen to be invoked by ClassName::member, and adhere to the class access specifiers. Their storage is defined somewhere outside the class; storage is not created each time you instantiated an object of the class. Pointers to class members are special in semantics and syntax. A pointer to a static member is a normal pointer in all regards.

virtual functions in a class needs the this pointer, and is very coupled to the class, hence they can't be static.

Waxen answered 30/11, 2009 at 15:33 Comment(1)
Only non-static functions need a this pointer. static functions are not specific to an instance, and would not need it. So - that's not a reason virtual static members are impossible.Finding
F
7

Well , quite a late answer but it is possible using the curiously recurring template pattern. This wikipedia article has the info you need and also the example under static polymorphism is what you are asked for.

Frumpish answered 5/2, 2013 at 0:25 Comment(0)
E
4

This question is over a decade old, but it looks like it gets a good amount of traffic, so I wanted to post an alternative using modern C++ features that I haven't seen anywhere else.

This solution uses CRTP and SFINAE to perform static dispatching. That, in itself, is nothing new, but all such implementations I've found lack strict signature checking for "overrides." This implementation requires that the "overriding" method signature exactly matches that of the "overridden" method. This behavior more closely resembles that of virtual functions, while also allowing us to effectively overload and "override" a static method.

Note that I put override in quotes because, strictly speaking, we're not technically overriding anything. Instead, we're calling a dispatch method X with signature Y that forwards all of its arguments to T::X, where T is to the first type among a list of types such that T::X exists with signature Y. This list of types considered for dispatching can be anything, but generally would include a default implementation class and the derived class.

Implementation

#include <experimental/type_traits>

template <template <class...> class Op, class... Types>
struct dispatcher;

template <template <class...> class Op, class T>
struct dispatcher<Op, T> : std::experimental::detected_t<Op, T> {};

template <template <class...> class Op, class T, class... Types>
struct dispatcher<Op, T, Types...>
  : std::experimental::detected_or_t<
    typename dispatcher<Op, Types...>::type, Op, T> {};


// Helper to convert a signature to a function pointer
template <class Signature> struct function_ptr;

template <class R, class... Args> struct function_ptr<R(Args...)> {
    using type = R (*)(Args...);
};


// Macro to simplify creation of the dispatcher
// NOTE: This macro isn't smart enough to handle creating an overloaded
//       dispatcher because both dispatchers will try to use the same
//       integral_constant type alias name. If you want to overload, do it
//       manually or make a smarter macro that can somehow put the signature in
//       the integral_constant type alias name.
#define virtual_static_method(name, signature, ...)                            \
    template <class VSM_T>                                                     \
    using vsm_##name##_type = std::integral_constant<                          \
        function_ptr<signature>::type, &VSM_T::name>;                          \
                                                                               \
    template <class... VSM_Args>                                               \
    static auto name(VSM_Args&&... args)                                       \
    {                                                                          \
        return dispatcher<vsm_##name##_type, __VA_ARGS__>::value(              \
            std::forward<VSM_Args>(args)...);                                  \
    }

Example Usage

#include <iostream>

template <class T>
struct Base {
    // Define the default implementations
    struct defaults {
        static std::string alpha() { return "Base::alpha"; };
        static std::string bravo(int) { return "Base::bravo"; }
    };

    // Create the dispatchers
    virtual_static_method(alpha, std::string(void), T, defaults);
    virtual_static_method(bravo, std::string(int), T, defaults);
    
    static void where_are_the_turtles() {
        std::cout << alpha() << std::endl;  // Derived::alpha
        std::cout << bravo(1) << std::endl; // Base::bravo
    }
};

struct Derived : Base<Derived> {
    // Overrides Base::alpha
    static std::string alpha(){ return "Derived::alpha"; }

    // Does not override Base::bravo because signatures differ (even though
    // int is implicitly convertible to bool)
    static std::string bravo(bool){ return "Derived::bravo"; }
};

int main() {
    Derived::where_are_the_turtles();
}
Esra answered 26/1, 2021 at 21:24 Comment(0)
T
3

I think what you're trying to do can be done through templates. I'm trying to read between the lines here. What you're trying to do is to call a method from some code, where it calls a derived version but the caller doesn't specify which class. Example:

class Foo {
public:
    void M() {...}
};

class Bar : public Foo {
public:
    void M() {...}
};

void Try()
{
    xxx::M();
}

int main()
{
    Try();
}

You want Try() to call the Bar version of M without specifying Bar. The way you do that for statics is to use a template. So change it like so:

class Foo {
public:
    void M() {...}
};

class Bar : public Foo {
public:
    void M() {...}
};

template <class T>
void Try()
{
    T::M();
}

int main()
{
    Try<Bar>();
}
Tobi answered 30/11, 2009 at 15:59 Comment(3)
If you indent your code 4 spaces you can get it automatically formatted. Alternatively I believe you can use the back tick to achieve the same purpose inline.Hesitate
This is the obvious I missed. Thank you. Still, pubic members are weird.Demarco
M() is not static function. how is it called T::M()?Ethbin
C
2

No, Static member function can't be virtual .since virtual concept is resolved at run time with the help of vptr, and vptr is non static member of a class.due to that static member function can't acess vptr so static member can't be virtual.

Chintzy answered 26/6, 2015 at 5:30 Comment(2)
Only instance-specific virtual methods require instances' vtable. You could have a static - one-per-class - vtable. And if you want instances to know about, just point from the instance's vtable also to the class statics vtable.Finding
However dynamic dispatch doesn't necessarily require the object pointer to be passed (explicitely or implicitely). What he seem to be after is to combine dynamic dispatch without necessarily having to pass an object pointer, which in turn would allow the method to be called without an object (in which case one would use static dispatch of course). There's actually nothing in that that makes it impossible - except that C++ doesn't have (direct) support for it.Acalia
C
1

No, its not possible, since static members are bound at compile time, while virtual members are bound at runtime.

Caius answered 30/11, 2009 at 15:35 Comment(1)
not anymore since C++20 introduced constexpr virtualsAstrosphere
L
1

If your desired use for a virtual static is to be able to define an interface over the static section of a class then there is a solution to your problem using C++20 concept's.

class ExBase { //object properties
  public: virtual int do(int) = 0;
};

template <typename T> //type properties
concept ExReq = std::derived_from<T, ExBase> && requires(int i) { //~constexpr bool
  {
    T::do_static(i) //checks that this compiles
  } -> std::same_as<int> //checks the expression type is int
};

class ExImpl : virtual public ExBase { //satisfies ExReq
  public: int do(int i) override {return i;} //overrides do in ExBase
  public: static int do_static(int i) {return i;} //satisfies ExReq
};

//...

void some_func(ExReq auto o) {o.do(0); decltype(o)::do_static(0);}

(this works the same way on members aswell!)

For more on how concepts work: https://en.cppreference.com/w/cpp/language/constraints

For the standard concepts added in C++20: https://en.cppreference.com/w/cpp/concepts

Laciniate answered 11/9, 2021 at 14:24 Comment(0)
J
1

It exists, but...

If you want a static, virtual then you already have it - simply don't use this.

Disclaimer: What is static virtual

I feel there's a lot of confusion by C++ programmers not familiar with the term as used in other languages. In Python for instance, a "static virtual" (@staticmethod) is virtual method that doesn't accept a self (this) argument, but can still be called -virtually- from an object instance. Of course, the this pointer must have existed at some point during the functions call in order to get the v-table, and its omission -if any- is purely syntactic sugar.

Why it's not explicit

C++ includes this implicitly in the function arguments, making little reason to introduce this feature. To put it another way, there would be zero difference between an explicitly declared @staticmethod like Python and a normal C++ function that simply didn't make use of this".

One could imagine a performance gain made by taking this out the function arguments when it isn't needed, but at this point we'd be second guessing whether it makes any difference given its already in use, and whether or not the compiler strips unused arguments out already.

Justinejustinian answered 17/8, 2023 at 14:52 Comment(0)
F
0

First, the replies are correct that what the OP is requesting is a contradiction in terms: virtual methods depend on the run-time type of an instance; static functions specifically don't depend on an instance -- just on a type. That said, it makes sense to have static functions return something specific to a type. For example, I had a family of MouseTool classes for the State pattern and I started having each one have a static function returning the keyboard modifier that went with it; I used those static functions in the factory function that made the correct MouseTool instance. That function checked the mouse state against MouseToolA::keyboardModifier(), MouseToolB::keyboardModifier(), etc. and then instantiated the appropriate one. Of course later I wanted to check if the state was right so I wanted write something like "if (keyboardModifier == dynamic_type(*state)::keyboardModifier())" (not real C++ syntax), which is what this question is asking.

So, if you find yourself wanting this, you may want to rething your solution. Still, I understand the desire to have static methods and then call them dynamically based on the dynamic type of an instance. I think the Visitor Pattern can give you what you want. It gives you what you want. It's a bit of extra code, but it could be useful for other visitors.

See: http://en.wikipedia.org/wiki/Visitor_pattern for background.

struct ObjectVisitor;

struct Object
{
     struct TypeInformation;

     static TypeInformation GetTypeInformation();
     virtual void accept(ObjectVisitor& v);
};

struct SomeObject : public Object
{
     static TypeInformation GetTypeInformation();
     virtual void accept(ObjectVisitor& v) const;
};

struct AnotherObject : public Object
{
     static TypeInformation GetTypeInformation();
     virtual void accept(ObjectVisitor& v) const;
};

Then for each concrete Object:

void SomeObject::accept(ObjectVisitor& v) const {
    v.visit(*this); // The compiler statically picks the visit method based on *this being a const SomeObject&.
}
void AnotherObject::accept(ObjectVisitor& v) const {
    v.visit(*this); // Here *this is a const AnotherObject& at compile time.
}

and then define the base visitor:

struct ObjectVisitor {
    virtual ~ObjectVisitor() {}
    virtual void visit(const SomeObject& o) {} // Or = 0, depending what you feel like.
    virtual void visit(const AnotherObject& o) {} // Or = 0, depending what you feel like.
    // More virtual void visit() methods for each Object class.
};

Then the concrete visitor that selects the appropriate static function:

struct ObjectVisitorGetTypeInfo {
    Object::TypeInformation result;
    virtual void visit(const SomeObject& o) {
        result = SomeObject::GetTypeInformation();
    }
    virtual void visit(const AnotherObject& o) {
        result = AnotherObject::GetTypeInformation();
    }
    // Again, an implementation for each concrete Object.
};

finally, use it:

void printInfo(Object& o) {
    ObjectVisitorGetTypeInfo getTypeInfo;
    Object::TypeInformation info = o.accept(getTypeInfo).result;
    std::cout << info << std::endl;
}

Notes:

  • Constness left as an exercise.
  • You returned a reference from a static. Unless you have a singleton, that's questionable.

If you want to avoid copy-paste errors where one of your visit methods calls the wrong static function, you could use a templated helper function (which can't itself be virtual) t your visitor with a template like this:

struct ObjectVisitorGetTypeInfo {
    Object::TypeInformation result;
    virtual void visit(const SomeObject& o) { doVisit(o); }
    virtual void visit(const AnotherObject& o) { doVisit(o); }
    // Again, an implementation for each concrete Object.

  private:
    template <typename T>
    void doVisit(const T& o) {
        result = T::GetTypeInformation();
    }
};
Fibster answered 20/8, 2013 at 14:39 Comment(2)
virtual static methods, had they existed, would not depend on anything in an instance - but the instance would need to know its type to invoke them. This can be worked out by a compiler (e.g. by using some per-class single data structure with pointers to virtual static methods and members.) It is certainly not a contradiction in terms.Finding
Whether or not it's a contradiction in terms is a question of semantics. One could imagine C++ allowing calling statics from an instance (e.g., Foo foo; ... foo::bar(); instead of Foo::bar();). That's not unlike decltype(foo)::bar(); but that again would be statically bound. The visitor approach seems a reasonable way to get this behavior without just making the static method be a virtual const method.Fibster
D
0

With c++ you can use static inheritance with the crt method. For the example, it is used widely on window template atl & wtl.

See https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern

To be simple, you have a class that is templated from itself like class myclass : public myancestor. From this point the myancestor class can now call your static T::YourImpl function.

Delectable answered 9/11, 2018 at 11:32 Comment(0)
C
-1

I had a browse through the other answers and none of them seem to mention virtual function tables (vtable), which explains why this is not possible.

A static function inside a C++ class compiles to something which is effectively the same as any other function in a regular namespace.

In other words, when you declare a function static you are using the class name as a namespace rather than an object (which has an instance, with some associated data).

Let's quickly look at this...

// This example is the same as the example below
class ExampleClass
{
    static void exampleFunction();

    int someData;
};

// This example is the same as the example above
namespace ExampleClass
{
    void exampleFunction();

    // Doesn't work quite the same. Each instance of a class
    // has independent data. Here the data is global.
    int someData;
}

With that out of the way, and an understanding of what a static member function really is, we can now consider vtables.

If you declare any virtual function in a class, then the compiler creates a block of data which (usually) precedes other data members. This block of data contains runtime information which tells the program at runtime where in memory it needs to jump to in order to execute the correct (virtual) function for each instance of a class which might be created during runtime.

The important point here is "block of data". In order for that block of data to exist, it has to be stored as part of an instance of an object (class). If your function is static, then we already said it uses the name of the class as a namespace. There is no object associated with that function call.

To add slightly more detail: A static function does not have an implicit this pointer, which points to the memory where the object lives. Because it doesn't have that, you can't jump to a place in memory and find the vtable for that object. So you can't do virtual function dispatch.

I'm not an expert in compiler engineering by any means, but understanding things at least to this level of detail is helpful, and (hopefully?) makes it easy to understand why (at least in C++) static virtual does not make sense, and cannot be translated into something sensible by the compiler.

Carabao answered 20/10, 2022 at 9:10 Comment(6)
In this very specific case, the so called "this" pointer is only useful for deciding which virtual implementation to call. In practice, "this" is used to figure out which subclass to refer to. So, I guess the OP wants a method that you can opt between a "this" pointer or a "subclass type".Anselm
@AndréCaldas If you know the precise details of exactly how the virtual function call is done feel free to edit this answer and add that detail. I didn't try to go into detail for that because I can't confidently say I know how it is done exactly ... and it may differ between different compiler implementations. (Maybe) I can imagine at least two ways it could be done.Carabao
There are already good answers to this question. I don't agree when people say it is "not possible". Even if it is not possible to declare a function virtual and static at the same time, it should be... and there is no technical argument that proves that such a feature would be. Such a function would not use the "this" pointer for anything other then determining which subclass' static counterpart to call. You would not be able to reference other members or access methods that use the "this". That way you would be able to call it with the class name or with an instance.Anselm
@AndréCaldas That doesn't make any sense because a static function does not use virtual dispatch. It is impossible because you cannot have virtual dispatch without an instance of an object. Now you could call a virtual function which calls a static member function, but use cases for such things are rare. I agree, in principle you could have a language extension which allow virtual static functions, but by definition such a thing is nonsensical. Virtual functions are usually called in the contexts of polymorphic behavior, which necessitates having an object.Carabao
@AndréCaldas In other words - what application would such a virtual static function have? There is none. What problem would it address? You have no class data to manipulate.Carabao
The class data is the "class". You use the this pointer to access the virtual table and determine what the class is. The rule would be to access only this information. It is like having two versions of the function. One static that you would call Subclass::myVS, and one virtual, so you could take a Parent* p and call p->myVS(). The correct static function would be called. Both do not access any instance data. Only static data. It is very presumptuous to make such firm statements... we do have to be very careful when we hire people...Anselm
H
-2

Maybe you can try my solution below:

class Base {
public:
    Base(void);
    virtual ~Base(void);

public:
    virtual void MyVirtualFun(void) = 0;
    static void  MyStaticFun(void) { assert( mSelf != NULL); mSelf->MyVirtualFun(); }
private:
    static Base* mSelf;
};

Base::mSelf = NULL;

Base::Base(void) {
    mSelf = this;
}

Base::~Base(void) {
    // please never delete mSelf or reset the Value of mSelf in any deconstructors
}

class DerivedClass : public Base {
public:
    DerivedClass(void) : Base() {}
    ~DerivedClass(void){}

public:
    virtual void MyVirtualFun(void) { cout<<"Hello, it is DerivedClass!"<<endl; }
};

int main() {
    DerivedClass testCls;
    testCls.MyStaticFun(); //correct way to invoke this kind of static fun
    DerivedClass::MyStaticFun(); //wrong way
    return 0;
}
Holeandcorner answered 24/3, 2011 at 5:26 Comment(1)
Yeah, I know, 4 years. Explaining the -score for those who don't want to read the code in that much details. Base::mSelf refers to the MOST RECENTLY constructed instance of any derived class, even if that instance has been destructed. so class D1 : public Base ...; class D2 : public Base ...; ...; D1* pd1 = new D1(); D2* pd2 = new D2(); pd1->MyStaticFun(); /* calls D2::MyVirtualFun() */ delete pd2; pd1->MyStaticFun(); /* calls via deleted pd2 */ Which is NOT what is wanted.Stocks
H
-3

Like others have said, there are 2 important pieces of information:

  1. there is no this pointer when making a static function call and
  2. the this pointer points to the structure where the virtual table, or thunk, are used to look up which runtime method to call.

A static function is determined at compile time.

I showed this code example in C++ static members in class; it shows that you can call a static method given a null pointer:

struct Foo
{
    static int boo() { return 2; }
};

int _tmain(int argc, _TCHAR* argv[])
{
    Foo* pFoo = NULL;
    int b = pFoo->boo(); // b will now have the value 2
    return 0;
}
Hesitate answered 30/11, 2009 at 15:49 Comment(3)
Technically, this is undefined behavior. You cannot deference a null pointer for any reason. The only things that you can do with a null pointer is a) assign another pointer to it and b) compare it with another pointer.Rescue
Furthermore, you can only compare it for equality (or inequality_ with another pointer, not ordering. I.e. p < null, p >= null etc are all undefined as well.Gate
@Rescue - For completeness you can also safely call delete on a null pointer.Questionary

© 2022 - 2024 — McMap. All rights reserved.