I'm writing a module system for my program, where individual modules are initialised and shutdown by a system.
how this works is I call an Init()
function that will initialise a static pointer of the class.
this works and is fine, however: I would like to abstract this into a class so the api is easier to maintain, but I don't know how to change the pointer type of the derived class automatically
for example, if I have the base class IModule
:
class IModule {
public:
protected:
result Init();
result Shutdown();
private:
static IModule* s_instance;
};
is there a way I can write this class so that the derived class can be written as
class Derived : public IModule {
protected:
result Init();
result Shutdown();
}
and have Derived::s_instance
evaluate to a Derived*
CodePudding user response:
No, you can't have a variable whose type depends on the type of this
. However, you can have a variable whose type depends on a template parameter.
template <typename T>
class IModule {
private:
static T* s_instance;
};
class Derived : public IModule<Derived> {
// The s_instance in this class is of type Derived*.
}
This is called the curiously recurring template pattern and it's used to do all sorts of tricks in C . It may not work for your use case (for instance, you can no longer have a list of IModule
which all have different derived types), but depending on what exactly you're doing this may be the way to go.
CodePudding user response:
You can do this as long as the return types are covariant, i.e., Derived::Init()
returns something derived from Derived::IModule()
's return type. Which is I think the case here. A simplified version:
#include <iostream>
struct IModule {
virtual IModule* Init() = 0;
private:
static IModule* s_instance;
};
class Derived : public IModule {
Derived* Init() override { std::cout << "1" << std::endl; return this; }
};
int main() {
IModule* ptr = new Derived();
ptr->Init(); // compile-time type: IModule, runtime: Derived
}