Does public static functions of base class become member functions of derived class if base class is inherited publicly ?

Hi ppl,

I am trying to run the following code but getting error.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>

template <typename T>
class Base {
  public :
    static T& Get() {
      static T t;
      return t;
    }
};

class Derived : public Base<Derived> {
  private :
    Derived() {}
};

int main() {
  Derived& d = Derived::Get();
  return 0;
}



prog.cpp: In instantiation of ‘static T& Base<T>::Get() [with T = Derived]’:
prog.cpp:18:24:   required from here
prog.cpp:7:14: error: ‘Derived::Derived()’ is private within this context
     static T t;
              ^
prog.cpp:14:4: note: declared private here
    Derived() {}
    ^~~~~~~


I have following questions
[1] Derived is publically derived from Base, doesn't it makes Get() a member
function of Derived too ?
[2] If [1] is true, and Get becomes a member function of Derived, then why
it's not able to call the private constructor of Derived.
[3] Assume we have multiple classes to be implemented as Singleton, is there
a way we can do it using templates with something similar to the above
example?



Kindly note that I understand :
1) We can make the above code work by adding following line to the code.
1
2
3
4
5
class Derived : public Base<Derived> {
  private :
    Derived() {}
    friend Base<Derived>; // line added to Derived
};


2) We can make Get() as "non static virtual function" and override in the
derived classes.
I am not looking for the above mentioned solutions. Though, please let me know if this(these) is(are) the only possible solutions to achieve this kind of design.
Last edited on
Thanks @lastchance for having a look :).

Please note that my primary question is (In context of code from my 1st post) :
[1] Derived is publically derived from Base, doesn't it makes Get() a member
function of Derived too ?

[2] If [1] is true, and Get() becomes a member function of Derived, then why
it's not able to call the private constructor of Derived.


lastchance wrote:

What is that intended to do?

Assume that we have multiple singleton classes to be defined which share functions f1(), f2(), f3()... and assume we can't use virtual functions.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>

template <typename T>
class Base {
  public :
    static T& Get() {
      static T t;
      return t;
    }
    void f1() {}
    void f2() {}
    void f3() {}
};

class Singleton1 : public Base<Singleton1> {
  private :
    Singleton1() {}
};

class Singleton2 : public Base<Singleton2> {
  private :
    Singleton2() {}
};

int main() {
  Singleton1& s1 = Singleton1::Get();
  Singleton2& s2 = Singleton2::Get();
  return 0;
}
Last edited on
0) singletons are an anti-pattern, don't make more of them.

[1] Derived is publically derived from Base, doesn't it makes Get() a member function of Derived too ?

Colloquially people would say that "static member functions are inherited", although what is really said in the language specification is that your Base::get can be called using the syntax Derived::get() or d.get(); from outside the scope of Derived, and with plain get() inside the scope of Derived or of a member function of Derived..

[2] If [1] is true, and Get becomes a member function of Derived, then why
it's not able to call the private constructor of Derived.

see above.
Even though called Base::get using the syntax Derived::get, this has no effect on the name lookup for the things used inside Base::get.

[3] Assume we have multiple classes to be implemented as Singleton, is there
a way we can do it using templates with something similar to the above
example?

Singletons are bad. But if you really want to explore the possibilities, here's another trick:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
template <typename T>
class Base {
  public :
    static T& Get() {
      static T t(PassKey{});
      return t;
    }
 private:
    struct PassKey{};
  protected:
    Base(PassKey) {}    
};

class Derived : public Base<Derived> {
  using Base<Derived>::Base;
};

int main() {
  Derived& d = Derived::Get(); // this works
  Derived fail; // this fails
}


but friending the base is really more readable and, I think, common
Thanks a lot @Cubbi for the detailed explanation :)
Topic archived. No new replies allowed.