0

I keep on reading that static virtual member functions doesn't make sense because virtual functions will be called based on the type of the class at run time and static functions are not tied to instance. But I am unable to understand this clearly.

1) A virtual table will be created at compile time if we have one or more virtual functions in a class and this virtual table is an array of addresses of those virtual functions. When we create object, a hidden pointer will be created which will be filled with the address of v-table. So when v-table is created at compile time, why compiler can't add addresses of static functions also? If addresses of static functions are also added into v-table, static virtual functions can be possible and we can call those static functions based on the type of class. Is there any specific reason, why this can't be done?

2) Some websites stated that "The static member function can't access non-static data members/functions of a class. The vPTR is non-static data member, hence a static member function can't access vPTR.". But I didn't understand why static member functions need to have access to vPTR, once we reach the function definition through vPTR and v-table.

To be more clear :

class base {
    public:
        static void test() {
        }
};

class derived : public base {
    public:
        static void test() {
        }
};

derived *obj = new derived();
obj->test();

If we add addresses of static member functions to v-table, we can call derived version of test. Please let me know if I am wrong.

kadina
  • 5,042
  • 4
  • 42
  • 83

2 Answers2

2

When we create object, a hidden pointer will be created which will be filled with the address of v-table.

Correct.

So when v-table is created at compile time, why compiler can't add addresses of static functions also?

It can, but there is no way for the vtable to be reached statically, because the vtable pointer is in the object, as you said above, not in the class, so what would be the point?

But I didn't understand why static member functions need to have access to vPTR, once we reach the function definition through vPTR and v-table.

Once you reach the function definition through VPTR and v-table without an instance how? Consider:

class MyClass
{
    static virtual void myStaticFunction {}
}

// ...

MyClass::myStaticFunction();

No object, so no VPTR, so the vtable cannot possibly be found.

Stephen Newell
  • 7,330
  • 1
  • 24
  • 28
user207421
  • 305,947
  • 44
  • 307
  • 483
  • Why you are trying to access MyClass.myStaticFunction()? – kadina Apr 27 '18 at 00:17
  • What I am asking is if we create an object dynamically (using new) and we can call the static member function through the dynamic object. – kadina Apr 27 '18 at 00:18
  • 1
    Then it's not really a static member function. – T.C. Apr 27 '18 at 00:18
  • 1
    @kadina Because that's how you access static member functions. If making them virtual means that you are also going to insist on having an object instance, you make the syntax above impossible. You can't just cut out chunks of the language. You also make static member functions completely pointless. – user207421 Apr 27 '18 at 00:19
  • 3
    Shouldn't it be `MyClass::myStaticFunction()`? – Barmar Apr 27 '18 at 00:37
  • 1
    Maybe the suggestion is that `ptr->f()` could call either `Base::f` or `Derived::f`, depending on the dynamic type of `*ptr`; but `f` doesn't use `this`. Apparently other languages do allow that concept – M.M Apr 27 '18 at 01:48
0

Static member functions are just normal, plain, good old functions inside the namespace of the class. Therefore, callers always know their addresses at compile time (since they have no runtime dispatch of any kind), so there is no need to keep the address in the VPTR.

Note that, in any case, you can "override" static functions in derived classes (they are just different functions in different namespaces):

struct A
{
    static int f() { return 1; }
};

struct B : A
{
    static int f() { return 2; }
};

int f()
{
    return A::f() + B::f(); // returns 3
}

However, if B::f() is commented out, f() returns 2 since B::f() is inherited from A.

In other words, A::f() will always call A::f() (no dynamic dispatch); but the behavior of calling B::f() differs depending on whether there is a B::f() (calls that one) or not (calls A::f()).

Acorn
  • 24,970
  • 5
  • 40
  • 69
  • "*you can "override" static functions in derived classes*" - that is more an *overload* than an *override*. An *override* would imply that calling `A::f()` would somehow call `B::f()`, and that is simply not possible. – Remy Lebeau Apr 27 '18 at 00:51
  • @RemyLebeau Indeed, I quoted "override" because it is only meant in the sense of "overwriting inherited function" (i.e. without the dynamic dispatch side). – Acorn Apr 27 '18 at 10:47