C++ polymorphism: how to create derived class objects - c++

I have an abstract base class called BaseStrategy. It contains one pure virtual function calculateEfficiency(). There are two classes ConvolutionStrategy and MaxPoolStrategy which derive from this base class and implement their own specific version of calculateEfficiency().
Here is some code:
class BaseStrategy {
public:
explicit BaseStrategy();
virtual ~BaseStrategy() = default;
private:
virtual double calculateEfficiency(mlir::Operation* op) = 0;
};
class ConvolutionStrategy : public BaseStrategy {
private:
double calculateEfficiency(mlir::Operation* op)
{
//some formula for convolution
return 1;
}
};
class MaxPoolStrategy : public BaseStrategy {
private:
double calculateEfficiency(mlir::Operation* op)
{
//some formula for MaxPool
return 1;
}
};
Now I have another class called StrategyAssigner. It has method calculateAllLayerEfficiencies() whose purpose is to iterate over all layers in a network. Depending on the type of layer there is a switch statement and should call the correct calculateEfficiency() depending on the layer type.
class StrategyAssigner final {
public:
explicit StrategyAssigner(){};
public:
void calculateAllLayerEfficiencies() {
// Logic to iterate over all layers in
// a network
switch (layerType) {
case Convolution:
// Call calculateEfficiency() for Convolution
break;
case MaxPool:
// Call calculateEfficiency() for MaxPool
break;
}
};
}
int main ()
{
StrategyAssigner assigner;
assigner.calculateAllLayerEfficiencies();
}
My question is, should I store references of objects Convolution and MaxPool in the class StrategyAssigner so that I can call the respective calculateEfficiency().
Or could you suggest a better way to call calculateEfficiency(). I don't really know how to create the objects (stupid as that sounds).
I can't make calculateEfficiency() static as I need them to be virtual so that each derived class can implemented its own formula.

If you included complete code I could give a more detailed answer, but you need to store BaseStrategy pointers that are initialized with derived class instances. Here's an example made from some of your code:
std::vector<std::unique_ptr<BaseStrategy>> strategies;
strategies.emplace_back(new ConvolutionStrategy);
strategies.emplace_back(new MaxPoolStrategy);
for (int i = 0; i < strategies.size(); ++i) {
std::unique_ptr<BaseStrategy>& pStrat = strategies[i];
pStrat->calculateEfficiency(...);
}
Note that this won't compile because I don't have enough details from the code you posted to make it so, but this shows how to exploit polymorphism in the way that you need.
Also, I used smart pointers for memory management; use these at your discretion.

You can indeed use runtime polymorphism here:
Declare ~BaseStrategy virtual (you are already doing it ;-)
If you are never going to instantiate a BaseStrategy, declare one of its methods as virtual pure, e.g. calculateEfficiency (you are already doing it as well!). I would make that method const, since it doesn't look it's going to modify the instance. And it will need to be public, because it will need to be accessed from StrategyAnalyser.
Declare calculateEfficiency as virtual and override in each of the subclasses. It could also be final if you don't want subclasses to override it.
I'd keep a std::vector of smart pointers to BaseStrategy at StrategyAssigner. You can use unique_ptrs if you think this class is not going to be sharing those pointers.
The key point now is that you create heap instances of the subclasses and assign them to a pointer of the base class.
class StrategyAssigner final {
public:
void addStrategy(std::unique_ptr<BaseStrategy> s) {
strategies_.push_back(std::move(s));
}
private:
std::vector<std::unique_ptr<BaseStrategy>> strategies_{};
};
int main()
{
StrategyAssigner assigner;
assigner.addStrategy(std::make_unique<ConvolutionStrategy>());
}
Then, when you call calculateEfficiency using any of those pointers to BaseStrategy, the runtime polymorphism will kick in and it will be the method for the subclass the one that will be actually called.
class ConvolutionStrategy : public BaseStrategy {
private:
virtual double calculateEfficiency() const override {
std::cout << "ConvolutionStrategy::calculateEfficiency()\n";
return 10;
}
};
class MaxPoolStrategy : public BaseStrategy {
private:
virtual double calculateEfficiency() const override {
std::cout << "MaxPoolStrategy::calculateEfficiency()\n";
return 20;
}
};
class StrategyAssigner final {
public:
void calculateAllLayerEfficiencies() {
auto sum = std::accumulate(std::cbegin(strategies_), std::cend(strategies_), 0,
[](auto total, const auto& strategy_up) {
return total + strategy_up->calculateEfficiency(); });
std::cout << "Sum of all efficiencies: " << sum << "\n";
};
};
int main()
{
StrategyAssigner assigner;
assigner.addStrategy(std::make_unique<ConvolutionStrategy>());
assigner.addStrategy(std::make_unique<MaxPoolStrategy>());
assigner.calculateAllLayerEfficiencies();
}
// Outputs:
//
// ConvolutionStrategy::calculateEfficiency()
// MaxPoolStrategy::calculateEfficiency()
// Sum of all efficiencies: 30
[Demo]

Related

How to construct a template class type that can be substituted for subclasses and then called generically?

I have 10 Coin types: BTC, ETH, Shift etc. For this I have a superclass "Coin" and subclasses for each of those coins. Then I have a pointer to a "Coin" type, so that I can call each of the subclasses no matter what subtype they are.
Problem is, I only know how to do this in Java and not in C++. I have a hard time searching for the correct terms, because I don't really know what to search for other than "generics". What I want is something like this:
// Superclass
class Coin {
public:
virtual void handleCoin();
};
// Subclass
class BTC: public Coin {
void handleCoin();
}
BTC::BTC() = default;
BTC::~BTC() = default;
BTC::handleCoin() {
std::cout << "handling BTC" << std::endl;
}
// Subclass
class ETH: public Coin {
void handleCoin();
}
ETH::ETH() = default;
ETH::~ETH() = default;
ETH::handleCoin() {
std::cout << "handling ETH" << std::endl;
}
// Execute
int main() {
Coin* coin;
coin = BTC();
coin.handleCoin();
coin = ETH();
coin.handleCoin();
return 0;
}
I want this to print:
handling BTC
handling ETH
I know I need to work with templates, but I cannot find a specific example of this specific case.
Also, my constructors don't take arguments, so I guess my template declaration would be something like
template<>
Yet all the examples I see work with
template<typename T>
and then use type T as function arguments like calling
max<float, float>
max<double, double>
But that's not what I'm looking for. Is there a way to translate this example above to working C++ code?
From the code posted I don't see a need for templates, virtual methods work without templates. To fix your code in main you need to use pointers/references and also have a virtual destructor.
class Coin {
public:
virtual void handleCoin();
virtual ~Coin()=default;
};
class BTC: public Coin {
public:
BTC::BTC() = default;
//Destructor of a derived class is automatically virtual if the base class's one is.
void handleCoin();
}
// Subclass
class ETH: public Coin {
void handleCoin();
ETH::ETH() = default;
//Still virtual even if you specify otherwise
ETH::~ETH() = default;
}
int main() {
Coin* coin;
coin = new BTC();//Returns BTC* <--pointer
coin->handleCoin();
delete coin;//Calls Coin::~Coin() -> thus the need for virtual so BTC::~BTC is called instead.
coin = new ETH();
coin->handleCoin();
delete coin;//Same, calls ETH::~ETH()
return 0;
}
Manual memory management is error-prone, from C++11 there's a better approach which should be strongly preferred:
int main() {
std::unique_ptr<Coin> coin;//Hides the pointer, but still has pointer-like semantics
coin = std::make_unique<BTC>();
coin->handleCoin();
//Automatically frees old memory
coin = std::make_unique<BTC>();
coin->handleCoin();
//Calls unique ptr's dtor because coin is local variable, which again frees the memory correctly.
return 0;
}

Parent class referencing child variable

I have several similar classes inheriting from the same Base-Class/Interface (Base class 1), and they share a couple similar functions, but then also have their own distinct functions. They all also have their own member variables of different classes, and each of those inherits from the same Base-Class/Interface (Base class 2). Is it possible to define a variable in Base class 1, of type Base class 2, then in the actual implementation of classes using Base class 1, have the variable of type Base class 2 be its proper type. Kinda hard to explain, so simplified example below.
//Base-Class 1
class Shape
{
public Shape() {}
ShapeExtra m_var;
//The common functions
public GetVar(){ return m_var; }
}
class Circle : Shape
{
public Circle() { m_var = new CircleExtra(); }
public void CircleFunc()
{
m_var.CircleExtraFunc();
}
}
class Triangle : Shape
{
public Triangle() { m_var = new TriangleExtra(); }
public void TriangleFunc()
{
m_var.TriangleExtraFunc();
}
}
.
.
.
//Base_Class 2
class ShapeExtra
{
public ShapeExtra() {}
}
class CircleExtra : ExtraClass
{
public CircleExtra() {}
void CircleExtraFunc() {//Do stuff}
}
class TriangleExtra : ExtraClass
{
public TriangleExtra() {}
void TriangleExtra() {//Do stuff}
}
.
.
.
So, I need the m_var in the child classes to be kept it as its own unique version. Because right now (w/o the extra CircleExtra m_var;), the GetVar() works, but in CircleFunc, m_var is still type of ShapeExtra, and thus doesn't know that CircleExtraFunc exists. I could cast m_var each time I wanted to do that, but that is repetitive and not worth it in my real-world case. Is there a way to utilize the functions in unique classes based off of ShapeExtra, while keeping the GetVar() function in Shape?
Please ask questions if there is anything I left out.
Simply with inheritance and without using pointers it is not possible, as C++ is a statically-and-strictly-typed language.
You can inherit both the variable and the function, but you'll need to cast function return value.
You can also override the function to make it return the concrete type, but then you have to cast the variable inside the function.
You can also declare the same var with the concrete class in subclasses, but then you just hide the variable in the superclass and inherit nothing.
I'd rather go for a solution using templates. Make the type of the variable a template type and extend the template using a concrete type in subclasses. It'll work perfectly.
It's been a long time since I last programmed in C++ and I beg your pardon if there are errors in the following example. I'm sure you can easily make it work.
template <class S>
class Shape {
S m_var;
//......
public:
S var () {
return m_var;
}
//.......
}
class Circle: Shape <CircleExtra> {
// var method returns CircleExtra
//......
}
Edit:
Regarding some comment, to allow virtual invocation of the method, it is possible to use correlated return types. Something like the following example.
class Shape {
public:
virtual ShapeExtra *var () = 0;
}
template <typename SE>
class ConcreteShape: Shape {
public:
virtual SE *var() {
return &m_var;
}
// Constructor, etc.
private:
SE m_var;
}
Or some variation. Now concrete shapes can benefit from extending the template, as long as SE * is correlated with ShapeExtra * (the type parameter extends ShapeExtra). And you can vall the method transparently through Shape interface.
Using pointers, this is totally possible.
Using your example, you could do something like this:
#include <iostream>
#include <memory>
using namespace std;
//Extras
class ShapeExtra
{
public:
ShapeExtra() {}
void ShapeFunc() { std::cout << "Shape"; }
virtual ~ShapeExtra() = default; //Important!
};
class Shape
{
public:
std::unique_ptr<ShapeExtra> m_var;
//require a pointer on construction
//make sure to document, that Shape class takes ownership and handles deletion
Shape(ShapeExtra* p):m_var(p){}
//The common functions
ShapeExtra& GetVar(){ return *m_var; }
void ShapeFunc() {m_var->ShapeFunc();}
};
class CircleExtra : public ShapeExtra
{
public:
void CircleExtraFunc() {std::cout << "Circle";}
};
class Circle : public Shape
{
CircleExtra* m_var;
public:
Circle() : Shape(new CircleExtra()) {
m_var = static_cast<CircleExtra*>(Shape::m_var.get());
}
void CircleFunc()
{
m_var->CircleExtraFunc();
}
};
int main() {
Circle c;
//use the ShapeExtra Object
c.GetVar().ShapeFunc();
//call via forwarded function
c.ShapeFunc();
//call the circleExtra Function
c.CircleFunc();
return 0;
}
Test it on ideone
Note the use of pointers and a virtual destructor:
By using a virtual destructor in the ShapeExtra base class, you make it possible to destruct an object of any derived class, using a ShapeExtra*. This is important, because
by using a std::unique_ptr<ShapeExtra> instead of a plain C-pointer, we make sure that the object is properly deleted on destruction of Shape.
It is probably a good idea to document this behaviour, i.e. that Shape takes the ownership of the ShapeExtra*. Which especially means, that we do not delete CirleExtra* in the Circle destructor
I decided here to require the ShapeExtra* on construction, but its also possible to just use std::unique_ptr::reset() later and check for nullptr on dereferencing Shape::m_var
Construction order is this: On calling the constructor of Circle, we first create a new CircleExtra which we pass to Shape before finally the constructor of Circle is executed.
Destruction order is Circle first (was created last), then Shape which also destructs the ShapeExtra for us, including (via virtual function) the CircleExtra
I would recommend the following approach:
class ShapeExtra
{
public:
virtual ~ShapeExtra() { }
virtual void SomeCommonShapeFunc() { std::cout << "Shape"; }
};
class Shape
{
public:
virtual ShapeExtra &GetVar() = 0; // Accessor function.
};
Note that the class Shape does not have any data members at all. After that for each derived class you need:
class CircleExtra : public ShapeExtra
{
public:
void SomeCommonShapeFunc() { std::cout << "Circle"; }
};
class Circle : public Shape
{
CircleExtra m_var; // Data member with circle specific class.
public:
virtual ShapeExtra &GetVar() { return m_var; }
};
Implementation of virtual method in Circle will return reference to the base class ShapeExtra. This will allow using this extra in the base class.
Note that pointers and templates are not used at all. This simplifies the overall design.

Efficiently manage same code for single element or array of elements

I have a large class with many methods. This class has a subclass that manages a different situation.
Just to clear it up with an example the actual situation is the following:
class Logic {
public:
virtual void method()
{
Something::getInstance()->doSomething();
}
};
class ArrayLogic : public Logic {
private:
Something** array;
public:
void method() override
{
for (int i = 0; i < AMOUNT; ++i)
array[i]->doSomething();
}
};
Now this pattern repeats itself in multiple methods and I'd like to have just one implementation without trading for performance (since some of this methods are actually already proven to require efficiency).
I was thinking if it's possible with C++11 to have a template solution approach which is able to manage this situation at compile time without the necessity to duplicate the code.
Mind that the array doesn't make sense to exist for Logic so having a Something*[1] is not a viable option.
An additional problem is that at the moment Something** array is not directly contained in ArrayLogic but resides in another class, so it's more like
class ArrayLogic : public Logic {
private:
Container* container;
public:
void method() override {
for (int i = 0; i < AMOUNT; ++i)
if (container->array[i])
container->array[i]->doSomething();
}
}
While having to check for container->array[i] != nullptr may seems strange the fact is that the position is relevant, so an element removed from the array doesn't cause a shift of the successive element but leaves a hole.
I'd try and create separate classes for single and multiplayer games. Base both of these on a base class LogicBase that has a method(Something*) function that calls doSomething() on its parameter. This is what #Pradhan was referring to.
In your main game, you can use a LogicBase* to refer to either a SinglePlayerLogic or a MultiPlayerLogic object and call the relevant method() using a virtual function call.
I'm passing what is stored in Container to the constructor of MultiPlayerLogic. But it could be in a separate class and accessed that way. Similarly, it may be cleaner to pass a Something to the constructor of SinglePlayerLogic, but I wanted to keep the code structure close to your original, so didn't do this.
It initially looks funny for LogicBase to call to a subclass, then have those subclasses call the protected method(Something*) back in the super class. I've seen it elsewhere as a design pattern, but can't recall it's name.
#include <iostream>
#include <vector>
const int AMOUNT = 5;
struct Something {
void doSomething() { std::cout << "Something::doSomething\n"; }
static Something* getInstance() { static Something s; return &s; }
};
class LogicBase {
public:
virtual void method() = 0;
protected:
void method(Something* s) { s->doSomething(); }
};
class SinglePlayerLogic : public LogicBase {
public:
void method() override
{
std::cout << "SinglePlayer::method\n";
LogicBase::method(Something::getInstance());
}
};
class MultiPlayerLogic : public LogicBase {
public:
MultiPlayerLogic(Something **s) : players(s) {}
void method() override
{
std::cout << "MultiPlayer::method\n";
for (int i = 0; i < AMOUNT; ++i) {
if (players[i] == nullptr) {
continue;
}
std::cout << i << " ";
LogicBase::method(players[i]);
}
}
private:
Something** players;
};
int main() {
LogicBase* lb;
SinglePlayerLogic spl;
lb = &spl;
lb->method();
std::vector<Something*> players{AMOUNT};
MultiPlayerLogic mpl(players.data());
lb = &mpl;
lb->method();
}

C++ passing base type to pure virtual function

i want to understand the behavior of pure virtual functions in derived class when passing to it an argument of same type as (abstract) base class.
to clarify the question, i took the following code from GeeksForGeeks and modified it:
namespace example {
enum Type {ENGINEER, MANAGER};
class Employee
{
private:
const Type worker;
public:
Employee(const Type& worker) : worker(worker) {}
virtual ~Employee {}
virtual void raiseSalary(const Employee&) = 0;
{ /* common raise salary code */ }
virtual void promote(const Employee&) = 0;
{ /* common promote code */ }
};
class Manager: public Employee {
private:
int degree;
public:
//<constructor>\\
virtual void raiseSalary(const Employee&)
{ /* Manager specific raise salary code, may contain
increment of manager specific incentives*/ }
virtual void promote(const Employee&)
{ /* Manager specific promote */ }
};
}
Now, how can we get access to the field degree in derived class Manager inorder to update his degree? since the passed argument to raiseSalary(Employee& employee) could be Manager or Engineer
I think there are two ways to handle that problem. Let's start with some really bad solution: using casting. In that case dynamic_cast. You can try to down cast a type. If dynamic_cast isn't able to do that it is going to return a null pointer or throw an exception (depends on wheather you cast a pointer or a value/reference type). But that approach is going to force you to adapt your casts as more Manager, Engineer types are going to come. You might also need to use friend to allow specific classes to access internals of others. friend is not going to be inherited in the hierarchy, so you are going to end up with many friends => broken, broken, broken :(
An alternative would be to use the Visitor Pattern: http://en.wikipedia.org/wiki/Visitor_pattern
Using the visitor pattern you can also make a base no-op visitor and finer grained Visitors to handle specific stuff. Just a small example (with specific visitors without derivation):
namespace example {
class SalaryRaisingVisitor;
class EmployeePromotingVisitor;
class Employee
{
public:
Employee() {}
//don't forget to implement the copy constructor: read more about rule of 3!!!
virtual ~Employee {}
virtual void accept(SalaryRaisingVisitor const&) = 0;
virtual void accept(EmployeePromotingVisitor const&) = 0;
};
class Manager: public Employee {
private:
int degree;
public:
//<constructorS>
virtual void accept(SalaryRaisingVisitor const& v)
{
v.visit(*this, degree);
}
virtual void accept(EmployeePromotingVisitor const& v)
{
v.visit(*this, degree);
}
};
class Engineer: public Employee {
public:
//<constructorS>
virtual void accept(SalaryRaisingVisitor const& v)
{
v.visit(*this);
}
virtual void accept(EmployeePromotingVisitor const& v)
{
v.visit(*this);
}
};
class SalaryRaisingVisitor
{
void visit(Manager& m, int& degree) //might be const if no internal state changes
{
//...
}
void visit(Engineer& e) //might be const if no internal state changes
{
//...
}
};
}
At the end as you deal with C++, try to avoid virtual functions :) and move everything to static polymorphism :)
You are getting the concept of virtual functions with classes wrong. The class "knows" what it is (via vtable), so you can just write it as class function, not as static global function. Each function inside the class knows all class variables, so you don't have to pass an object of the class.
namespace example {
enum Type {ENGINEER, MANAGER};
class Employee
{
private:
const Type worker;
public:
Employee(const Type& worker) : worker(worker) {}
virtual ~Employee {}
virtual void raiseSalary() = 0;
{ /* common raise salary code */ }
virtual void promote() = 0;
{ /* common promote code */ }
};
class Manager: public Employee {
private:
int degree;
public:
//<constructor>\\
virtual void raiseSalary()
{
//the Employed standard code
Employee::raiseSalary(); //This won't compile since you set the virtual function = 0
//Manager specific raise salary code
degree = 0; //this lazy bastards should do real work like coding stuff
}
virtual void promote()
{
Employee::promote(); //employee common code. This won't compile since you set the virtual function = 0
/* Manager specific promote */
degree = degree * 2;
}
};
Employee array[10];
array[0] = Manager(); //create a manager object on the stack
array[1] = Manager(); //create a manager object on the stack
array[0].raiseSalary(); //Only Mananer0 gets raiseSalary
/*the manager object in array[0] uses its virtual function
to the manager raiseSalary function. The Manager RaiseSalary function
in this case calls the base class raiseSalary function explicitly
via Employee::raiseSalary(); */
You should rather structure your code like this:
class Employee
{
virtual void raiseSalary() = 0;
virtual void promote() = 0;
};
class Manager: public Employee
{
virtual void raiseSalary()
{ /* Manager specific raise salary code, may contain... */ }
virtual void promote()
{ /* Manager specific promote */ }
};
int main()
{
Manager bob;
bob.promote(); // <--- Proper method in the Manager class will be called.
// Current instance will always have the right class.
}
In other words you should seek opportunity to pass the specific derived class as the this parameter. Unfortunately this will not work in complex cases when multiple params are needed. But well, this was the idea of the language designers. The perfect language is not developed yet.
I think that you can't and it's the wanted behaviour.
The only way to do this is to cast you argument (which is quite complicated in C++ since you have four different kind of casting). Other solution is to give to any employee a grade attribute.
Alexis.

polymorphism and encapsulation of classes

I'm trying to take advantage of the polymorphism in c++, but I'm from a c world, and I think what I've done could be done more cleverly in a OOP way.
I have 2 classes that has exactly the same public attributes, and I want to "hide" that there exists 2 different implementations. Such that I can have a single class where I can use the member functions as If i were accessing the specific class.
An very simple implementation of what I'm trying to accomplish is below:
#include <iostream>
class subber{
private:
int id;
public:
int doStuff(int a,int b) {return a-b;};
};
class adder{
private:
int id;
public:
int doStuff(int a, int b) {return a+b;};
};
class wrapper{
private:
int type_m;
adder cls1;
subber cls2;
public:
wrapper(int type) {type_m=type;};//constructor
int doStuff(int a, int b) {if(type_m==0) return cls1.doStuff(a,b); else return cls2.doStuff(a,b);};
};
int main(){
wrapper class1(0);
std::cout <<class1.doStuff(1,3) <<std::endl;
wrapper class2(1);
std::cout <<class2.doStuff(1,3) <<std::endl;
return 0;
}
I have 2 classes called "subber" and "adder" which both have a member function called doStuff, which will either subtract of add 2 numbers.
This I wrap up in a class "wrapper", which has both "adder" and "subber" as private variables, and a doStuff public member function. And given which value I instantiate my "wrapper" class with, my "wrapper" class will simply relay the "doStuff" to the correct class.
This code does of cause work, but I would like to avoid instatiating both "subber" and "adder" in my wrapper class, since I will only need of them in each of my "wrapper" classes.
Thanks
There are many ways to do it. Through a Factory for example.
But to keep it simple - make a base abstract class that defines the interface, and derive your classes from it to implement the functionality. Then you only need to make the distinction once, when you create the class, after that you don't care, you just call the interface functions.
your code would look something like that.
class DoStuffer
{
public:
virtual int doStuff(int, int)=0;
virtual ~DoStuffer(){}; // Because Tony insists:-) See the comments
}
class subber: public DoStuffer{
public:
virtual int doStuff(int a,int b) {return a-b;};
};
class adder: public DoStuffer{
public:
virtual int doStuff(int a, int b) {return a+b;};
};
int main(){
DoStuffer *class1 = new adder();
DoStuffer *class2 = new subber();
std::cout <<class1->doStuff(1,3) <<std::endl;
std::cout <<class2->doStuff(1,3) <<std::endl;
delete class1; // don't forget these:-)
delete class2;
return 0;
}
This is one of the more idiomatic ways to use the C++ class system to accomplish what you want. Both adder and subber publicly inherit from wrapper, which is now an abstract base class. The doStuff method is now a (pure) virtual function. And instead of being a simple instance of wrapper, the "encapsulated" object is now a reference to a wrapper.
#include <iostream>
class wrapper {
public:
virtual int doStuff(int a, int b) = 0;
};
class subber : public wrapper {
public:
virtual int doStuff(int a,int b) {return a - b;}
};
class adder : public wrapper {
public:
virtual int doStuff(int a, int b) {return a + b;}
};
int main(){
// actual objects
adder impl1;
subber impl2;
// in real code, the wrapper references would probably be function arguments
wrapper& class1 = impl1;
std::cout << class1.doStuff(1,3) << std::endl;
wrapper& class2 = impl2;
std::cout << class2.doStuff(1,3) << std::endl;
return 0;
}
(Not using any factory pattern in this example, since it's not obvious that it's needed or what the question is about.)
Exactly what was last said.
Make a base class, and have a virtual function |doStuff| in it.
Then you can derive any number of classes out from it, all have to implement the above virtual function, in whatever way they want to.
Then you can just do the following
BaseClass *object1 = new DerivedClass1();
BaseClass *object2 = new DerivedClass2();
..
You can even do
object1 = object2;
And then they point to the same object (i.e. an object of type |DerivedClass2|)
But remember, when you do objectn->doStuff(), the function that will be executed will be what the pointer points to at run-time, and not at compile time.
i.e. if I do object1->doStuff() DerivedClass2's doStuff will be called because we already did `object1 = object2;
You may want to Google and read about
Polymorphism/ Run-time Polymorphism
Virtual Functions in C++
You can read Factory Method, which is something that is known as a Design Pattern, but later in life.
Thanks
The classic run-time polymorphic approach is:
struct Operation
{
virtual ~Operation() { } // guideline: if there are any virtual functions,
// provide virtual destructor
virtual int doStuff(int, int) const;
};
struct Subber : Operation
{
int doStuff(int a, int b) const { return a - b; }
};
struct Adder : Operation
{
int doStuff(int a, int b) const { return a + b; }
};
enum Operations { Add, Subtract };
struct Operation* op_factory(Operations op)
{
if (op == Add) return new Adder;
if (op == Subtract) return new Subber;
throw std::runtime_error("unsupported op");
}
int main()
{
Operation* p1 = op_factory(Add);
std::cout << p1->doStuff(1,3) <<std::endl;
Operation* p2 = op_factory(Subtract);
std::cout << p2->doStuff(1,3) <<std::endl;
delete p1;
delete p2;
}
From the Standard 5.3.5/5 "In the first alternative (delete object), if the static type of the operand is different from its dynamic type, the static type shall be a base class of the operand's dynamic type and the static type shall have a virtual destructor or the behavior is undefined.", which is why you must use the virtual keyword on the base class destructor.
It's noteworthy that in your example the type of operation to perform was communicated to the wrapper class using a function argument of 0 or 1... this is what suggests you want run-time polymorphism. For example, if the 0 or 1 value was based on a command line argument, file content, keyboard input etc., then the factory method above can pass a corresponding Add or Subtract value and receive an appropriately-behaving object derived from Operation. This concept of creating an instance of a run-time polymorphic type based on run-time values is known as a factory.
If you really only need compile-time polymorphism, you can do some interesting things with templates such as:
template <class Operation>
void output(int a, int b)
{
std::cout << Operation::doStuff(a, b) << std::endl;
std::cout << Operation::doStuff(a * 10, b * 10) << std::endl;
std::cout << Operation::doStuff(a * 100, b * 100) << std::endl;
}
int main()
{
output<adder>(1, 3);
output<subber>(1, 3);
}
FWIW, your approach is probably slightly faster than the virtual function approach (as it can potentially do more inlining), but not as clean, extensible, maintainable or scalable.
I think what you're looking for is virtual functions. If you declare a function virtual in your base class, you can do things like make a vector containing multiple objects derived from your base class, but when you call on a particular object it will execute it's own method.