Home > OS >  Is there a way to have a member parameter type be a pointer to a derived class
Is there a way to have a member parameter type be a pointer to a derived class

Time:08-07

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
}
  • Related