Is there a way to write an abstract base class that looks like it's forcing an implementer to choose among a myriad of pure virtual functions?
The abstract base classes I'm writing define a mathematically tedious function, and request that the deriving code define only building block functions. The building block functions can be generalized to take on more arguments, though. For example, in the code below, it might "make sense" to allow another_derived::first() to take three arguments. The "mathematically tedious" part of this is the multiplication by 3. Unsurprisingly, it won't allow won't compile unless I comment out the creation of d2. I understand why.
One option is to create different base classes. One would request a single parameter function to be defined, and the other would request a two parameter function to be defined. However, there would be an enormous amount of code being copy and pasted between the two base class' definition of final_result(). This is why I'm asking, so I don't write WET code.
Another option would be to have one pure virtual function, but change the signature so that its implementation can do either of these things. I want to explore this, but I also don't want to start using fancier techniques so that it puts a barrier to entry on the type of people trying to inherit from these base classes. Ideally, if the writers of the base class could get away with barely knowing any c++, that would be great. Also, it would be ideal if the inheritors didn't even have to know about the existence of related classes they could be writing.
#include <iostream>
class base{
public:
virtual int first(int a) = 0;
int final_result(int a) {
return 3*first(a);
}
};
class derived : public base {
public:
int first(int a) {
return 2*a;
}
};
class another_derived : public base {
public:
int first(int a, int b) {
return a + b;
}
};
int main() {
derived d;
std::cout << d.final_result(1) << "\n";
//another_derived d2; // doesn't work
return 0;
}
Not sure it matches exactly what you want, but with CRTP, you might do something like:
template <typename Derived>
struct MulBy3
{
template <typename... Ts>
int final_result(Ts... args) { return 3 * static_cast<Derived&>(*this).first(args...); }
};
class derived : public MulBy3<derived> {
public:
int first(int a) { return 2*a; }
};
class another_derived : public MulBy3<another_derived > {
public:
int first(int a, int b) { return a + b; }
};
With usage similar to
int main() {
derived d;
std::cout << d.final_result(1) << "\n";
another_derived d2;
std::cout << d2.final_result(10, 4) << "\n";
}
Demo
Related
I am reading some C++ material on dynamic_cast and there the following practice is considered bad:
class base{};
class derived1 d1 :public base{};
class derived2 d2 :public base
{
public:
void foo(){}
};
void baz(base *b)
{
if (derived2 *d2= dynamic_cast<derived2 *> (b) )
{
d2-> foo();
}
}
The remedy to this is to use the "capability query" using an empty pure virtual base class like following:
class capability_query
{
public:
virtual void foo()= 0;
};
class base{};
class derived1 d1 :public base{};
class derived2 d2 :public base, public capability_query
{
public:
virtual void foo(){}
};
void baz(base *b)
{
if (capability_query *cq= dynamic_cast<capability_query *> (b) )
{
cq-> foo();
}
}
My 1st question is why is the first code block considered bad?
The way I see it foo is only executed if d2 can be successfully downcasted from b in the baz function. So what is the issue here?!
My 2nd question is why is the second code block considered good? and how does this fix the issue, which I don't understand in the first place.
FYI, my google search for capability query returned http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Capability_Query
which seems to be basically code block1 and not code block2. I still don't get why an additional empty base class is considered a better practice?
EDIT:
here is the best possible answer I can think of.Since inside baz I am downcasting to a pointer type and not reference, in case the downcast is not successful , I will get a Null pointer and not std::bad_cast. So, assuming the cast goes wrong and I do get NULL pointer , but what if I am not supposed to execute Null->foo and if I may forget to test for NULL, so code block 1 could be a problem.
The way code block 2 fixes this, is by adding an empty class. Even if
dynamic_cast<capability_query *> (b)
fails and I get a null pointer , you cannot execute
null->foo since inside capability_query class this foo method is pure virtual. This is just a conjecture , but may be I am on the right path??!!
The academic answer would be that in object oriented design you should not depend on the implementation i.e. concrete classes. Instead you should depend on high-level components like interfaces and abstract base classes. You can read more about this design principle on Wikipedia.
The reason for this is to decouple the design which makes the code more manageable and maintainable.
Let's look at an example. You have a base class and a derived class:
struct Duck {
virtual ~Duck() {}
};
struct MallardDuck : public Duck {
void quack() const {
std::cout << "Quack!" << std::endl;
}
};
Let's say you have another class with a function taking a parameter Duck.
struct SoundMaker {
void makeSound(const Duck* d) {
if (const MallardDuck* md = dynamic_cast<const MallardDuck*>(d)) {
md->quack();
}
}
};
You can use the classes like this:
MallardDuck md;
SoundMaker sm;
sm.makeSound(&md);
Which outputs Quack!.
Now lets add another derived class RubberDuck:
struct RubberDuck : public Duck {
void squeak() const {
std::cout << "Squeak!" << std::endl;
}
};
If you want SoundMaker to use the class RubberDuck you must make changes in makeSound:
void makeSound(const Duck* d) {
if (const MallardDuck* md = dynamic_cast<const MallardDuck*>(d)) {
md->quack();
} else if (const RubberDuck* rd = dynamic_cast<const RubberDuck*>(d)) {
rd->squeak();
}
}
What if you need to add another type of duck and produce its sound? For every new type of duck you add, you will have to make changes in both the code of the new duck class and in SoundMaker. This is because you depend on concrete implementation. Wouldn't it be better if you could just add new ducks without having to change SoundMaker? Look at the following code:
struct Duck {
virtual ~Duck() {}
virtual void makeSound() const = 0;
};
struct MallardDuck : public Duck {
void makeSound() const override {
quack();
}
void quack() const {
std::cout << "Quack!" << std::endl;
}
};
struct RubberDuck : public Duck {
void makeSound() const override {
squeak();
}
void squeak() const {
std::cout << "Squeak!" << std::endl;
}
};
struct SoundMaker {
void makeSound(const Duck* d) {
d->makeSound(); // No dynamic_cast, no dependencies on implementation.
}
};
Now you can use both duck types in the same way as before:
MallardDuck md;
RubberDuck rd;
SoundMaker sm;
sm.makeSound(&md);
sm.makeSound(&rd);
And you can add as many duck types as you wish without having to change anything in SoundMaker. This is a decoupled design and is much easier to maintain. This is the reason for why it is bad practise to down-cast and depend on concrete classes, instead only use high-level interfaces (in the general case).
In your second example you're using a separate class to evaluate if the requested behaviour of the derived class is available. This might be somewhat better as you separate (and encapsulate) the behaviour-control code. It still creates dependencies to your implementation though and every time the implementation changes you may need to change the behaviour-control code.
The first example, where foo is called on d2->foo(), violates the Open-Closed Principle, which in this case means that you should be able to add or remove functionality in d2 without changing code in baz (or anywhere else). The code:
void baz(base *b)
{
if (capability_query *cq= dynamic_cast<capability_query *> (b) )
{
cq-> foo();
}
}
shows that baz depends on the definition of the class d2. If one day, the function d2::foo() is removed, the function baz will also have to be modified, otherwise you'll be a compiler error.
However, in the improved version, if an author decides to remove the foo capability of d2 by removing the base class capability_query, (or indeed if the foo capability were to be added to class d1) the function baz needs no modification, and the run time behavior will automatically be correct.
I have a couple of classes that share a common base class, with the exception that they differ in the way their methods work. So in the example below, Adder and Multiplier are the same except for the way in which their calculation is performed.
Is there a way to change "a" to a Multiplier on the fly? Do I need to implement methods which convert derived classes to each other? e.g. something like
a = a.asMultiplier()?
As you can see in the code below I tried reinterpret_cast to a Multiplier, with no luck, it still acts like an Adder. (gcc OS X v4.2.1)
#include <iostream>
class Base {
protected:
int a,b;
public:
Base(int a, int b) {
this->a = a;
this->b = b;
}
virtual ~Base() { }
virtual int calculate() = 0;
};
class Adder : public Base {
public:
Adder(int a, int b) : Base(a, b) {
}
int calculate() {
return this->a + this->b;
}
};
class Multiplier : public Base {
public:
Multiplier(int a, int b) : Base(a, b) {
}
int calculate() {
return this->a * this->b;
}
};
int main() {
Base* a = new Adder(3,4);
Base* m = new Multiplier(3,4);
std::cout << "Adder gives " << a->calculate() << std::endl;
std::cout << "Multiplier gives " << m->calculate() << std::endl;
a = reinterpret_cast<Multiplier*>(a);
std::cout << "Now adder gives " << a->calculate() << std::endl;
delete a;
delete m;
return 0;
}
The best thing that comes up to me to solve this, is implementing a copy constructor, taking the base class:
class Multiplier : public Base {
public:
Multiplier(int a, int b) : Base(a, b) {
}
explicit Multiplier(const Base& iBase) : Base(iBase.a, iBase.b) {
}
int calculate() {
return this->a * this->b;
}
};
But since I am not the most advanced c++ developer here, it might not be correct or other people might have a better idea, just trying :)
I would propose to decouple the object's data from its operations. This way you can easily construct one object from another, overtaking the data. So your "conversion" will look like this: Multiplier m = new Multiplier(a);
Doing it the way you are asking for is impossible in C++.
This seems to me that you would need utility classes that operate on data: Change your base class to a Data class whose purpose is only to store the data and pass the data explicitly to the Adder, Multiplier etc. classes.
You can still use inheritance in the utility classes if it makes sense after the above refactoring: in this case base would also operate on a Data object, instead of being the Data itself
It is probably a good idea to change your design. In general I would say that it is a good idea to used inheritance when there is some kind of commonality shared by base and derived classes, not only in terms of data, but in terms of behaviour. Whilst not being very helpful advice directly I would suggest maybe reading some books on object oriented design principles. Trying to cast types in the way you are really makes no sense.
I've two functions
MultiplyVerison1(T x, T y); // in class A
MultiplyVersion1(T x, T y); // in class B
Above functions are in separate non-template classes.
Now, as part of refactoring I'm trying to create a base class of A and B and creating a pure virtual MultiplyVersion1 but a templte function cannot be marked virtual.
So, how can we achieve the same with template functions?
You can't. There's no way to call a function template in a derived class through a pointer-to-base, that's what "function templates cannot be virtual" means.
You can think of this as being because it's the call that triggers the instantiation of the function template with a particular type T -- if you call it with int, but the dynamic type of the object you're calling it on isn't known until runtime (whether it's A or B or something else), then there's no way for the compiler to know that it needs to instantiate A::MultiplyVersion1<int> or B::MultiplyVersion1<int> or something else. Actually there's more to it than that, but I think that's enough.
You can bodge around particular cases, but you won't get the full effect of a virtual function. Something like:
struct Base {
template <typename T>
void MultiplyVersion1(const T &x, const T &y) {
A *athis = dynamic_cast<A*>(this);
if (athis) {
athis->MultiplyVersion1(x,y);
} else {
B *bthis = dynamic_cast<B*>(this);
if (bthis) {
bthis->MultiplyVersion1(x,y);
} else {
throw std::logic_error();
}
}
}
virtual ~Base() {}
};
Now when you call MultiplyVersion1<int> via a pointer-to-base, both A::MultiplyVersion1<int> and B::MutiplyVersion1<int> are instantiated. But of course you can't easily add new derived classes, which is a serious restriction.
You could also re-consider whether you really need dynamic polymorphism at all, but that depends entirely on how you're planning to use that base class. You seem to have done OK without it so far.
If all you want from the base class is code re-use for some other functions, then you don't need dynamic polymorphism. Leave MultiplyVersion1 out of the base class entirely (and maybe don't inherit publicly from the Base, instead inherit privately and bring in the functions you want to re-use with using statements). If the functions you want to define for re-use call MultiplyVersion1, then consider simulated dynamic binding via CRTP:
#include <iostream>
template <typename Derived>
struct Base {
template <typename T>
void MultiplyVersion2(const T &x, const T &y) {
static_cast<Derived&>(*this).MultiplyVersion1(x + 1, y + 1);
}
};
struct A : private Base<A> {
friend class Base;
template <typename T> void MultiplyVersion1(T x, T y) {
std::cout << x*y << "\n";
}
using Base::MultiplyVersion2;
};
struct B : private Base<B> {
friend class Base;
template <typename T> void MultiplyVersion1(T x, T y) {
std::cout << x << " * " << y << " = " << x*y << "\n";
}
using Base::MultiplyVersion2;
};
int main() {
A a;
a.MultiplyVersion2(1,2);
B b;
b.MultiplyVersion2(1,2);
}
I'm finding it difficult to describe this problem very concisely, so I've attached the code for a demonstration program.
The general idea is that we want a set of Derived classes that are forced to implement some abstract Foo() function from a Base class. Each of the derived Foo() calls must accept a different parameter as input, but all of the parameters should also be derived from a BaseInput class.
We see two possible solutions so far, neither we're very happy with:
Remove the Foo() function from the base class and reimplement it with the correct input types in each Derived class. This, however, removes the enforcement that it be implemented in the same manner in each derived class.
Do some kind of dynamic cast inside the receiving function to verify that the type received is correct. However, this does not prevent the programmer from making an error and passing the incorrect input data type. We would like the type to be passed to the Foo() function to be compile-time correct.
Is there some sort of pattern that could enforce this kind of behaviour? Is this whole idea breaking some sort of fundamental idea underlying OOP? We'd really like to hear your input on possible solutions outside of what we've come up with.
Thanks so much!
#include <iostream>
// these inputs will be sent to our Foo function below
class BaseInput {};
class Derived1Input : public BaseInput { public: int d1Custom; };
class Derived2Input : public BaseInput { public: float d2Custom; };
class Base
{
public:
virtual void Foo(BaseInput& i) = 0;
};
class Derived1 : public Base
{
public:
// we don't know what type the input is -- do we have to try to cast to what we want
// and see if it works?
virtual void Foo(BaseInput& i) { std::cout << "I don't want to cast this..." << std::endl; }
// prefer something like this, but then it's not overriding the Base implementation
//virtual void Foo(Derived1Input& i) { std::cout << "Derived1 did something with Derived1Input..." << std::endl; }
};
class Derived2 : public Base
{
public:
// we don't know what type the input is -- do we have to try to cast to what we want
// and see if it works?
virtual void Foo(BaseInput& i) { std::cout << "I don't want to cast this..." << std::endl; }
// prefer something like this, but then it's not overriding the Base implementation
//virtual void Foo(Derived2Input& i) { std::cout << "Derived2 did something with Derived2Input..." << std::endl; }
};
int main()
{
Derived1 d1; Derived1Input d1i;
Derived2 d2; Derived2Input d2i;
// set up some dummy data
d1i.d1Custom = 1;
d2i.d2Custom = 1.f;
d1.Foo(d2i); // this compiles, but is a mistake! how can we avoid this?
// Derived1::Foo() should only accept Derived1Input, but then
// we can't declare Foo() in the Base class.
return 0;
}
Since your Derived class is-a Base class, it should never tighten the base contract preconditions: if it has to behave like a Base, it should accept BaseInput allright. This is known as the Liskov Substitution Principle.
Although you can do runtime checking of your argument, you can never achieve a fully type-safe way of doing this: your compiler may be able to match the DerivedInput when it sees a Derived object (static type), but it can not know what subtype is going to be behind a Base object...
The requirements
DerivedX should take a DerivedXInput
DerivedX::Foo should be interface-equal to DerivedY::Foo
contradict: either the Foo methods are implemented in terms of the BaseInput, and thus have identical interfaces in all derived classes, or the DerivedXInput types differ, and they cannot have the same interface.
That's, in my opinion, the problem.
This problem occured to me, too, when writing tightly coupled classes that are handled in a type-unaware framework:
class Fruit {};
class FruitTree {
virtual Fruit* pick() = 0;
};
class FruitEater {
virtual void eat( Fruit* ) = 0;
};
class Banana : public Fruit {};
class BananaTree {
virtual Banana* pick() { return new Banana; }
};
class BananaEater : public FruitEater {
void eat( Fruit* f ){
assert( dynamic_cast<Banana*>(f)!=0 );
delete f;
}
};
And a framework:
struct FruitPipeLine {
FruitTree* tree;
FruitEater* eater;
void cycle(){
eater->eat( tree->pick() );
}
};
Now this proves a design that's too easily broken: there's no part in the design that aligns the trees with the eaters:
FruitPipeLine pipe = { new BananaTree, new LemonEater }; // compiles fine
pipe.cycle(); // crash, probably.
You may improve the cohesion of the design, and remove the need for virtual dispatching, by making it a template:
template<class F> class Tree {
F* pick(); // no implementation
};
template<class F> class Eater {
void eat( F* f ){ delete f; } // default implementation is possible
};
template<class F> PipeLine {
Tree<F> tree;
Eater<F> eater;
void cycle(){ eater.eat( tree.pick() ); }
};
The implementations are really template specializations:
template<> class Tree<Banana> {
Banana* pick(){ return new Banana; }
};
...
PipeLine<Banana> pipe; // can't be wrong
pipe.cycle(); // no typechecking needed.
You might be able to use a variation of the curiously recurring template pattern.
class Base {
public:
// Stuff that don't depend on the input type.
};
template <typename Input>
class Middle : public Base {
public:
virtual void Foo(Input &i) = 0;
};
class Derived1 : public Middle<Derived1Input> {
public:
virtual void Foo(Derived1Input &i) { ... }
};
class Derived2 : public Middle<Derived2Input> {
public:
virtual void Foo(Derived2Input &i) { ... }
};
This is untested, just a shot from the hip!
If you don't mind the dynamic cast, how about this:
Class BaseInput;
class Base
{
public:
void foo(BaseInput & x) { foo_dispatch(x); };
private:
virtual void foo_dispatch(BaseInput &) = 0;
};
template <typename TInput = BaseInput> // default value to enforce nothing
class FooDistpatch : public Base
{
virtual void foo_dispatch(BaseInput & x)
{
foo_impl(dynamic_cast<TInput &>(x));
}
virtual void foo_impl(TInput &) = 0;
};
class Derived1 : public FooDispatch<Der1Input>
{
virtual void foo_impl(Der1Input & x) { /* your implementation here */ }
};
That way, you've built the dynamic type checking into the intermediate class, and your clients only ever derive from FooDispatch<DerivedInput>.
What you are talking about are covariant argument types, and that is quite an uncommon feature in a language, as it breaks your contract: You promised to accept a base_input object because you inherit from base, but you want the compiler to reject all but a small subset of base_inputs...
It is much more common for programming languages to offer the opposite: contra-variant argument types, as the derived type will not only accept everything that it is bound to accept by the contract, but also other types.
At any rate, C++ does not offer contravariance in argument types either, only covariance in the return type.
C++ has a lot of dark areas, so it's hard to say any specific thing is undoable, but going from the dark areas I do know, without a cast, this cannot be done. The virtual function specified in the base class requires the argument type to remain the same in all the children.
I am sure a cast can be used in a non-painful way though, perhaps by giving the base class an Enum 'type' member that is uniquely set by the constructor of each possible child that might possibly inherit it. Foo() can then check that 'type' and determine which type it is before doing anything, and throwing an assertion if it is surprised by something unexpected. It isn't compile time, but it's the closest a compromise I can think of, while still having the benefits of requiring a Foo() be defined.
It's certainly restricted, but you can use/simulate coviarance in constructors parameters.
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.