Selective static member inheritance with CRTP - c++

so I have this class hierarchy using CRTP:
template <class T>
class A {
static Object x;
static OtherObject y;
}
class B : public A<B> {
}
class C : public A<C> {
}
The original idea is that B and C do not share instances of x and y, since A<B> and A<C> are considered separate classes. But suppose that it was determined, for resource savings, that 'x' should be a singleton instance shared by B and C while an instance of 'y' shoul still be created for each derived class. Is there a way to do this?
Thanks in advance.

You can make the class template derive from another class. Define x in the base class.
class ABase {
static Object x;
};
template <class T>
class A : public ABase {
static OtherObject y;
}
class B : public A<B> {
}
class C : public A<C> {
}

Related

Is this the right approach to count the number of base class objects created when there is a partial virtual inheritance involved?

From what I have learnt about virtual inheritance, whenever we have a class A (the base class), classes B, C, D (all these three virtually inherit class A) then if there is a class derived which inherits from B, C and D classes is instantiated then only a single object of class A would be created.
I tried to reason about the virtual inheritance by taking different cases:
Case 1:
Assume the derived class inherits only from class B and C. Even then only a single object of class A gets instantiated, right?
I tried to verify this using this code and it certainly seems to be the case:
#include <iostream>
using namespace std;
class A
{
public:
int a;
};
class B: virtual public A
{
public:
int b;
};
class C: virtual public A
{
public:
int c;
};
class D: virtual public A
{
public:
int d;
};
class derived: public B, public C
{
public:
int y;
};
int main()
{
derived dObj;
cout<<&(dObj.B::a)<<'\n';
cout<<&(dObj.C::a)<<'\n';
return 0;
}
Output:
0x7ffc8adac1c0
0x7ffc8adac1c0
Case 2:
Assume the derived class inherits from class B, C and D, but class D doesn't inherit class A virtually. In this case, 2 objects of class A get instantiated, right? - One for B, C and one for D.
I tried to verify this using this code and it certainly seems to be the case:
#include <iostream>
using namespace std;
class A
{
public:
int a;
};
class B: virtual public A
{
public:
int b;
};
class C: virtual public A
{
public:
int c;
};
class D: public A
{
public:
int d;
};
class derived: public B, public C, public D
{
public:
int y;
};
int main()
{
derived dObj;
cout<<&(dObj.B::a)<<'\n';
cout<<&(dObj.C::a)<<'\n';
cout<<&(dObj.D::a)<<'\n';
return 0;
}
Output:
0x7ffd512429c8
0x7ffd512429c8
0x7ffd512429bc
Now here is my question:
Are my observations correct? That is, instead of just 3 classes - B, C, D, let's assume we have n classes that inherit class A, if out of them, m (1<=m<=n) classes are inherited by another class named derived, and if out of those m classes only k (0<=k<=m) classes inherit class A virtually then the number of objects of class A that get instantiated when instantiating the derived class would be = 1+m-k (if k!=0) and m (when k=0), right?
From the content written in the cppreference website it is indeed the case:
See the first example under the virtual base classes section.

Initialization of static template member in CRTP

I try to initialize a static member of a CRTP base class. The base class holds a static template member of the derived class, while the derived class defines other data members. I want to statically initialize this variable. In code, a minimal example would be the following:
template<typename DERIVED>
class base {
public:
static DERIVED x;
};
class derived : public base<derived>
{
public:
int a;
};
int base<derived>::x {0};
int main()
{}
However, the above does not compile, but gives the error message error: specializing member 'base<derived>::x' requires 'template<>' syntax.
How can I get the static initialization to work?
The correct syntax is:
template <class T>
class base {
public:
static T x;
};
template <class T>
T base<T>::x{};
Note that you can't initialize x to a specific integer value, since then your base class won't compile when DERIVED is e.g. an std::string.
You probably also want your inheritance to be explicitly public or private. I.e.:
class derived : public base<derived> {
public:
int a;
};
Edit: To specialize x and it's initialization for specific types T, you have to specialize base itself. I.e.:
class A;
template <>
class base<A> {
public:
static int x;
};
// Note missing "template <>" here.
int base<A>::x{ 5 };
class A : public base<A> { };
This seems rather cumbersome, since you need to already forward declare A in this case before declaring the specialization. To me it feels you might want to rethink your design. Is this really required or is there a simpler way to accomplish what you want?
I have found the static initializer trick, which works in the above setting, too. It was described here and here. In the above context, it would be as follows:
#include <iostream>
template<typename DERIVED>
class base {
public:
static inline DERIVED x;
};
class derived : public base<derived>
{
public:
int a;
struct static_initializer {
static_initializer()
{
derived::x.a = 1;
}
};
static inline static_initializer static_initializer_;
};
int main()
{
std::cout << derived::x.a << "\n";
}
The above output the value 1.
Note: this works with C++17.

How to assign and retrive the value in member variable?

I am put/get value in/from subclass B from object of base class A. But I am not able to assign or get the value. My code is:
class A
{
};
class B: A
{
string SID;
};
class C: A
{
string Name;
};
class D : A
{
string Name;
};
class E
{
A a;
UINT32 AccessLevel;
};
.......
main()
{
E e;
}
Using object of e am trying to get the value of subclass B.
I need to get the SID from the class B?
Thanks,
The C++11 standard 11/3 says:
Members of a class defined with the keyword class are private by default.
at 11.2/2
In the absence of an access-specifier for a base class [...] private is assumed when the class is defined with the class-key class.
and at 11.2/1:
If a class is declared to be a base
class for another class using the private access specifier, the public and protected members of the base
class are accessible as private members of the derived class.
So what does that mean? First of all:
class A {};
class B : A {};
Here A, by virtue of 11.2/2 is inherited privately. This may be okay if you want to inherit variables and you want to implement getter/setters for a variable only in a derived class, but that's usually considered bad style.
In your case however, as stated by 11/3, your members are not inherited at all because they are private members:
class A
{
public:
int a; // inherited
protected:
int b; // inherited
private:
int c; // NOT inherited
};
and especially
class A { int a; };
is equivalent to
class A { private: int a; };
So you could make your members accessable from within your derived classes by making them public or protected (see 11.2/1):
class A { public: int a; };
class B : A {}; // privately inherits a
and if you wanted to make it acessable from outside of your derived classes you will have to inherit as public as well:
class A { public: int a; };
class B : public A {}; // publicly inherits a
but that's not what you usually would do. It's considered better style to make variables private and expose only getters and setters for those:
class A
{
public:
int get_a() const { return a_; }
void set_a(int val) { a_ = val; }
private:
int a_;
};
class B : public A {}; // now publicly inherits the getters and setters
// but not a_ itself

Static variables in static method in base class and inheritance

I have these C++ classes:
class Base
{
protected:
static int method()
{
static int x = 0;
return x++;
}
};
class A : public Base
{
};
class B : public Base
{
};
Will the x static variable be shared among A and B, or will each one of them have it's own independent x variable (which is what I want)?
There will only be one instance of x in the entire program. A nice work-around is to use the CRTP:
template <class Derived>
class Base
{
protected:
static int method()
{
static int x = 0;
return x++;
}
};
class A : public Base<A> { };
class B : public Base<B> { };
This will create a different Base<T>, and therefore a distinct x, for each class that derives from it.
You may also need a "Baser" base to retain polymorphism, as Neil and Akanksh point out.
There will only be one, shared by all three classes. If you want separate instances, you will have to create separate functions in the derived classes.
I am pretty sure it will be shared between A and B.
If you want independent variables you can use the "Curiously Recurring Template Pattern" like:
template<typename Derived>
class Base
{
protected:
static int method()
{
static int x = 0;
return x++;
}
};
class A : public Base<A>
{
};
class B : public Base<B>
{
};
Of course if you want polymorphism, you would have to define a even "Baser" class which Base derives from, as Base<A> is different from Base<B> like:
class Baser
{
};
template<typename Derived>
class Base : public Baser
{
protected:
static int method()
{
static int x = 0;
return x++;
}
};
class A : public Base<A>
{};
class B : public Base<B>
{};
Now A and B can also be polymorphic.
The former. Local static variables are bound to the method containing them, and method exists in one incarnation for all subclasses (in fact, for the whole app, even though the rest of the program does not see the method).
The variable will be shared - it is per-function - in this case the function it belongs to is Base::method(). However if class Base was a template class you would get one instance of the variable for each instantiation (each unique set of actual template parameters) of class Base template - each instantiation is a new function.
If you are making X as static then it will be shared among all the child classes. No issues with the function being static.

Create derived class instance from a base class instance without knowing the class members

Is this scenario even possible?
class Base
{
int someBaseMemer;
};
template<class T>
class Derived : public T
{
int someNonBaseMemer;
Derived(T* baseInstance);
};
Goal:
Base* pBase = new Base();
pBase->someBaseMemer = 123; // Some value set
Derived<Base>* pDerived = new Derived<Base>(pBase);
The value of pDerived->someBaseMemer should be equeal to pBase->someBaseMember and similar with other base members.
Why would you want to derive and pass the base pointer at the same time? Choose either, nothing stops you from having both. Use inheritance to do the job for you:
class Base
{
public:
Base(int x) : someBaseMemer(x) {}
protected: // at least, otherwise, derived can't access this member
int someBaseMemer;
};
template<class T>
class Derived : public T
{
int someNonBaseMemer;
public:
Derived(int x, int y) : someNonBaseMemer(y), T(x) {}
};
Derived<Base> d(42, 32); // usage
Though not the best of choices as design.
Why wouldn't you actually finish writing and compiling the code?
class Base
{
public: // add this
int someBaseMemer;
};
template<class T>
class Derived : public T
{
public: // add this
int someNonBaseMemer;
Derived(T* baseInstance)
: T(*baseInstance) // add this
{ return; } // add this
};
This compiles and runs as you specified.
EDIT: Or do you mean that someNonBaseMemer should equal someBaseMemer?
Declare someBaseMemr as public or change the declaration from class to struct:
class Base
{
public:
int someBaseMemer;
};
OR
struct Base
{
int someBaseMemr;
};
Remember that a class has private access to all members and methods by default. A struct provides public access by default.
Also, all derived classes should have public inheritance from Base.