My starting situation where I don't know what type to use in Base class:
class Base {
private:
virtual void doSomethingSpecific(?type param) = 0;
public:
// this function uses doSomethingSpecific
void doSomething() {...}
};
class Derived1 : public Base {
private:
void doSomethingSpecific(Derived1Type param) override;
};
class Derived2 : public Base {
private:
void doSomethingSpecific(Derived2Type param) override;
};
My solution using templates:
template<typename DerivedType>
class Base {
private:
virtual void doSomethingSpecific(DerivedType param) = 0;
public:
// this function uses doSomethingSpecific
void doSomething() {...}
};
class Derived1 : public Base<Derived1Type> {
private:
void doSomethingSpecific(Derived1Type param) override;
};
class Derived2 : public Base<Derived2Type> {
private:
void doSomethingSpecific(Derived2Type param) override;
};
This works, but I am posting this because it feels like this my not be the most optimal/straightforward approach? Also even though the header files are simple, templates significantly increased compile time.
Here is a more specific example of how I use doSomethingSpecific function:
template<typename DerivedType>
class Base {
std::vector<DerivedType> components;
private:
virtual void doSomethingSpecific(DerivedType param) = 0;
public:
Base(std::vector<DerivedType> components) {
this->components = components;
}
// this function uses doSomethingSpecific
void doSomething() {
doSomethingSpecific(components[0]);
}
};
class Derived1 : public Base<Derived1Type> {
private:
void doSomethingSpecific(Derived1Type param) override;
};
int main() {
std::vector<Derived1Type> components = {...};
Derived1 obj(components);
obj.doSomething();
}
I do not understand the first example of your code. It is not clear why there is public inheritance and a virtual method. In the second example it is apparent there there is no need for the virtual method. Base<A>
and Base<B>
are two unrelated types. Consequently Derived1
and Derived2
do not share a common base. There is no runtime polymorphism.
For compile time polymorphism you can employ the CRTP (curiously recurring template pattern). Your code looks already very similar. The major change I had to make is to remove the overriding (its not needed):
#include <iostream>
template<typename T>
struct Base {
void doSomething() {
static_cast<T*>(this)->doSomethingSpecific(typename T::type{});
}
};
struct Derived1 : public Base<Derived1> {
using type = int;
void doSomethingSpecific(type param) { std::cout << "hello int " << param; }
};
struct Derived2 : public Base<Derived2> {
using type = double;
void doSomethingSpecific(type param) { std::cout << "hello double " << param; }
};
int main() {
Derived1{}.doSomething();
Derived2{}.doSomething();
}
I also added a member alias type
that Base
can use to construct the parameter to pass to the methods. And for CRTP to work the base must be parametrized on the deriving class.
Again: Derived1
and Derived2
do not share a common base (as was the case already in your code).