I have a component in a software that can be described by an interface / virtual class.
Which non-virtual subclass is needed is decided by a GUI selection at runtime.
Those subclasses have unique methods, for which is makes no sense to give them a shared interface (e.g. collection of different data types and hardware access).
A minimal code example looks like this:
#include <iostream>
#include <memory>
using namespace std;
// interface base class
class Base
{
public:
virtual void shared()=0;
};
// some subclasses with shared and unique methods
class A : public Base
{
public:
void shared()
{
cout << "do A stuff\n";
}
void methodUniqueToA()
{
cout << "stuff unique to A\n";
}
};
class B : public Base
{
public:
void shared()
{
cout << "do B stuff\n";
}
void methodUniqueToB()
{
cout << "stuff unique to B\n";
}
};
// main
int main()
{
// it is not known at compile time, which subtype will be needed. Therefore: pointer has base class type:
shared_ptr<Base> basePtr;
// choose which object subtype is needed by GUI - in this case e.g. now A is required. Could also have been B!
basePtr = make_shared<A>();
// do some stuff which needs interface functionality... so far so good
basePtr->shared();
// now I want to do methodUniqueToA() only if basePtr contains type A object
// this won't compile obviously:
basePtr->methodUniqueToA(); // COMPILE ERROR
// I could check the type using dynamic_pointer_cast, however this ist not very elegant!
if(dynamic_pointer_cast<A>(basePtr))
{
dynamic_pointer_cast<A>(basePtr)->methodUniqueToA();
}
else
if(dynamic_pointer_cast<B>(basePtr))
{
dynamic_pointer_cast<B>(basePtr)->methodUniqueToB();
}
else
{
// throw some exception
}
return 0;
}
Methods methodUniqueTo*() could have different argument lists and return data which is omitted here for clarity.
I suspect that this problem isn't a rare case. E.g. for accessing different hardware by the different subclasses while also needing the polymorphic functionality of their container.
How does one generally do this?
For the sake of completeness: the output (with compiler error fixed):
do A stuff
stuff unique to A
You can have an enum which will represent the derived class. For example this:
#include <iostream>
#include <memory>
using namespace std;
enum class DerivedType
{
NONE = 0,
AType,
BType
};
class Base
{
public:
Base()
{
mType = DerivedType::NONE;
}
virtual ~Base() = default; //You should have a virtual destructor :)
virtual void shared() = 0;
DerivedType GetType() const { return mType; };
protected:
DerivedType mType;
};
// some subclasses with shared and unique methods
class A : public Base
{
public:
A()
{
mType = DerivedType::AType;
}
void shared()
{
cout << "do A stuff\n";
}
void methodUniqueToA()
{
cout << "stuff unique to A\n";
}
};
class B : public Base
{
public:
B()
{
mType = DerivedType::BType;
}
void shared()
{
cout << "do B stuff\n";
}
void methodUniqueToB()
{
cout << "stuff unique to B\n";
}
};
// main
int main()
{
shared_ptr<Base> basePtr;
basePtr = make_shared<B>();
basePtr->shared();
// Here :)
if(basePtr->GetType() == DerivedType::AType)
static_cast<A*>(basePtr.get())->methodUniqueToA();
else if(basePtr->GetType() == DerivedType::BType)
static_cast<B*>(basePtr.get())->methodUniqueToB();
return 0;
}
You can store an enum and initialize it at the constructor. Then have a Getter for that, which will give you the Type. Then a simple static cast after getting the type would do your job!
The goal of using polymorphism for the client is to control different objects with a single way. In other words, the client do not have to pay any attention to the difference of each object. That way, checking the type of each object violates the basic goal.
To achieve the goal, you will have to :
write the concrete method(methodUniqueToX()).
write a wrapper of the concrete method.
name the wrapper method abstract.
make the method public and interface/abstract.
class Base
{
public:
virtual void shared()=0;
virtual void onEvent1()=0;
virtual void onEvent2()=0;
};
// some subclasses with shared and unique methods
class A : public Base
{
private:
void methodUniqueToA()
{
cout << "stuff unique to A\n";
}
public:
void shared()
{
cout << "do A stuff\n";
}
void onEvent1()
{
this.methodUniqueToA()
}
void onEvent2()
{
}
};
class B : public Base
{
private:
void methodUniqueToB()
{
cout << "stuff unique to B\n";
}
public:
void shared()
{
cout << "do B stuff\n";
}
void onEvent1()
{
}
void onEvent2()
{
methodUniqueToB()
}
};
I have a dumb c++ design question. Is there a way for one class to have the same method names (hence, the same API) of the methods found in several classes?
My current situation is that I have a situation where I have classes
struct A
{
void foo() { std::cout << "A::foo" << std::endl;}
void boo() { std::cout << "A::boo" << std::endl;}
};
struct B
{
void moo() { std::cout << "B::moo" << std::endl;}
void goo() { std::cout << "A::goo" << std::endl;}
};
.... imagine possibly more
What I really want is another class that acts an interface for those of these functionalities. I might be misinterpreting as the facade design pattern for a simple interface that hides the complexity of instantiating classes above but still use their same interface.
struct C
{
void foo() { ... }
void boo() { ... }
void moo() { ... }
void goo() { ... }
};
For small number of methods shown above this is feasible by either declaring structs A and B or passing them in as parameters to struct C and call the methods of A and B in C but this is impracticable if A has 40 methods and B has 30 has methods. Redeclaring 70 methods with the same name in C to call the underlying methods of A and B seemed like a lot of redundancy for no reason if I could do better.
I thought of a second solutions of using a base class
struct base
{
void foo() { }
void boo() { }
void moo() { }
void goo() { }
};
struct A : public base
{
void foo() { std::cout << "A::foo" << std::endl;}
void boo() { std::cout << "A::boo" << std::endl;}
};
struct B : public base
{
void moo() { std::cout << "B::moo" << std::endl;}
void goo() { std::cout << "A::goo" << std::endl;}
};
To try and use a shared_ptr that has all the function definitions. e.g
std::shared_ptr<base> l_var;
l_var->foo();
l_var->boo();
l_var->moo();
l_var->goo();
That still doesn't quite give me what I want because half of the methods are defined in struct A while the other half is in struct B.
I was wondering if multiple inheritance would do the trick but in school I heard it's bad practice to do multiple inheritance (debugging is hard?)
Any thoughts or recommendations? Basically it's easier to manage struct A and B (and so on as it's own class for abstraction purposes). But would like the flexibility of somehow calling their methods in some wrapper where this complexity is hidden from the user.
I think that
Redeclaring 70 methods with the same name in C to call the underlying
methods of A and B
is the right path.
It is tempting to use multiple inheritance in cases like this to avoid writing pass-through code but I think that is generally a mistake. Prefer composition over inheritance.
I would question whether your user really wants to deal with one interface with 70 methods but if that's really what you want then I don't see why it is "impractical" to write the code in C:
class C {
A a;
B b;
public:
void foo() { return a.foo(); }
void boo() { return a.boo(); }
void moo() { return b.moo(); }
void goo() { return b.goo(); }
// ...
};
Live demo.
This has the advantage that you can easily change your mind in the future and replace A and B with something else without changing the interface of C.
You can hide the implementation of C further by using the PIMPL idiom or by splitting C into an abstract base class C and an implementation CImpl.
A Bridge Design Pattern will shine here. By decoupling abstraction from its implementation , many derived classes can used these implementations separately.
struct base {
protected:
struct impl;
unique_ptr<impl> _impl;
};
struct base::impl {
void foo() {}
void bar() {}
};
struct A :public base {
void foo() { _impl->foo(); }
};
struct B:public base {
void foo() { _impl->foo(); }
void bar() { _impl->bar(); }
};
Edited ( eg implementation)
#include <memory>
#include <iostream>
using namespace std;
struct base {
base();
protected:
struct impl;
unique_ptr<impl> _impl;
};
struct base::impl {
void foo() { cout << " foo\n"; }
void bar() { cout << " bar\n"; }
void moo() { cout << " moo\n"; }
void goo() { cout << " goo\n"; }
};
base::base():_impl(new impl()) {}
struct A :public base {
A():base() { }
void foo() { _impl->foo(); }
};
struct B:public base {
B() :base() { }
void foo() { _impl->foo(); }
void bar() { _impl->bar(); }
};
struct C :public base {
C() :base() { }
void foo() { _impl->foo(); }
void bar() { _impl->bar(); }
void moo() { _impl->moo(); }
void goo() { _impl->goo(); }
};
int main()
{
B b;
b.foo();
C c1;
c1.foo();
c1.bar();
c1.moo();
c1.goo();
return 0;
}
Use virtual multiple inheritance. The reason why
it's bad practice to do multiple inheritance
is because it directly will lead to ambiguous calls or redundant data, so you can use virtual inheritance to avoid it.
Learn how C++ implement iostream will help a lot, I thought.
I second Chris Drew's answer: not only multiple iharitance is bad, any inharitance is bad, compared to composition.
The purpose of the Fascade pattern is to hide complexity. As in, given your classes A and B with 40 and 30 methods, a Fascade would expose about 10 of them - those, needed by the user. Thus is avoided the problem of "if A has 40 methods and 30 has methods" then you have a big problem – n.m.
By the way, I love how you are using struct{} instead of class{public:}. This is quite controversial and the general consensus is it constitutes bad form, but stl does it and I do it.
Back to the question. If really all the 70 methods need to be exposed (!!), I would take a more pythonistic approach:
struct Iface
{
A _a;
B _b;
};
If you manage to make the fields const, things get even less bad. And for the third time - you are probably violating SRP with those large classes.
I want to make some "duel" with two "units".
I write class "duel" that constructs from two "units".
But some kind of "unit" is special (inherited from units) like heroes, bosses etc. And they want to use special strikes during battle.
But actually class "duel" doesn't know who is hero, or who is pure unit.
Code looks like this:
#include <iostream>
class unit{
public:
unit(){};
virtual void make_hit(){
std::cout<<"pure hit\n";
}
};
class hero:public unit {
public:
hero():unit(){};
void make_hit(){
std::cout<<"SUPER hit\n";
}
};
class duel {
unit *a, *b;
public:
duel(unit _a, unit _b):a(&_a),b(&_b){};
void start (){
a->make_hit();
b->make_hit();
}
};
int main(){
duel(unit(),hero()).start();
return 0;
}
I have two main problem.
First - I use refers to temporary objects in constructor. That objects illegal when duel::duel() finished.
Second - my hero turned into pure unit, and doesn't use "SUPER hit"
Is it possible fix it in elegant way (without changing call in main())?
Due to slicing, it's better to always use polymorphism together with
smart-pointers. This would be a possible design:
#include <iostream>
#include <memory>
#include <utility>
using namespace std;
class unit_base
{
public:
virtual ~unit_base() = default;
virtual void make_hit() =0;
};
class unit : public unit_base
{
public:
unit() = default;
virtual void make_hit() override
{
cout << "pure hit" << endl;
}
};
class hero : public unit_base
{
public:
hero() = default;
virtual void make_hit() override
{
cout << "SUPER hit" << endl;
}
};
class duel
{
public:
duel( shared_ptr<unit_base> a, shared_ptr<unit_base> b )
: a(a), b(b)
{}
void start()
{
auto aa = a.lock();
auto bb = b.lock();
if( aa && bb )
{
aa->make_hit();
bb->make_hit();
} else {
cout << "duelist expired" << endl;
}
}
private:
weak_ptr<unit_base> a, b;
};
int main()
{
// use with temporarys
duel{ make_shared<unit>(), make_shared<hero>() }.start();
cout << "-------------" << endl;
// use with variables
auto u = make_shared<unit>();
auto h = make_shared<hero>();
duel d{h,u};
d.start();
cout << "-------------" << endl;
// try to use with expired duelists
u.reset();
d.start();
}
Also remember to always have a virtual destructor in your base-class.
In
duel(unit _a, unit _b):a(&_a),b(&_b){};
You are slicing the objects as you are passing by value. To fix this you can take in pointers in your constructor
duel(unit* _a, unit* _b):a(_a),b(_b){};
And then you will need to change main() to create to objects and pass them to duel
int main(){
unit npc;
hero bob;
duel d(&npc,&bob);
d.start();
return 0;
}
The only way I have found for myself in C++ is make all combination of constructor in "duel" class. This solution not so elegant, need changing in "duel" code when added new class, and also this have overhead.
~duel(){
delete a;
delete b;
}
#define _cc(t1, t2) duel(t1 _a, t2 _b) : a(new t1 (_a)), b (new t2(_b)){}
_cc(unit,unit);
_cc(hero,unit);
_cc(unit,hero);
_cc(hero,hero);
#undef _cc
I also tried use template for this, but I can't find a way make automatic type determination.
I am trying to write a c++ abstract class and I can't figure out how to require implementers of this class to contain a static function.
For example:
class AbstractCoolThingDoer
{
void dosomethingcool() = 0; // now if you implement this class
// you better do this
}
class CoolThingDoerUsingAlgorithmA: public AbstractCoolthingDoer
{
void dosomethingcool()
{
//do something cool using Algorithm A
}
}
class CoolThingDoerUsingAlgorithmB: public AbstractCoolthingDoer
{
void dosomethingcool()
{
//do the same thing using Algorithm B
}
}
Now I'd like to do the coolthing without the details of how coolthing gets done. So I'd like to do something like
AbstractCoolThingDoer:dosomethingcool();
without needing to know how the coolthing gets done, but this seems to require a function that is both virtual and static which is of course a contradiction.
The rationale is that CoolThingDoerUsingAlgorithmB may be written later and hopefully the softare that needs cool things done won't have to be rewritten.
EDIT:Not sure I was clear on what I'm trying to accomplish. I have 3 criteria that I'm looking to satisfy
A library that uses abstractcoolthingdoer and does not need to be rewritten ever, even when another coolthingdoer is written that the library has never heard of.
If you try to write a coolthingdoer that doesn't conform to the required structure, then the executable that uses the library won't compile.
coolthingdoer has some static functions that are required.
I'm probably chasing down a poor design, so please point me to a better one. Am I needing a factory?
Maybe, something like this will help (see ideone.com example):
#include <iostream>
class A
{
protected:
virtual void do_thing_impl() = 0;
public:
virtual ~A(){}
static void do_thing(A * _ptr){ _ptr->do_thing_impl(); }
};
class B : public A
{
protected:
void do_thing_impl(){ std::cout << "B impl" << std::endl; }
};
class C : public A
{
protected:
void do_thing_impl(){ std::cout << "C impl" << std::endl; }
};
int main()
{
B b_;
C c_;
A::do_thing(&b_);
A::do_thing(&c_);
return (0);
}
EDIT: It seems to me the OP does not need run-time polymorphism, but rather compile-time polymorphism without need of class instance (use of static functions when the implementation is hidden in the derived classes, no instance required). Hope the code below helps to solve it (example on ideone.com):
#include <iostream>
template <typename Derived>
struct A
{
static void do_thing() { Derived::do_thing(); }
};
struct B : public A<B>
{
friend A<B>;
protected:
static void do_thing() { std::cout << "B impl" << std::endl; }
};
struct C : public A<C>
{
friend A<C>;
protected:
static void do_thing() { std::cout << "C impl" << std::endl; }
};
int main()
{
A<B>::do_thing();
A<C>::do_thing();
return (0);
}
EDIT #2: To force fail at compile-time in case user does not adhere to desired pattern, here is the slight modification at ideone.com:
#include <iostream>
template <typename Derived>
struct A
{
static void do_thing() { Derived::do_thing_impl(); }
};
struct B : public A<B>
{
friend A<B>;
protected:
static void do_thing_impl() { std::cout << "B impl" << std::endl; }
};
struct C : public A<C>
{
friend A<C>;
protected:
static void do_thing_impl() { std::cout << "C impl" << std::endl; }
};
struct D : public A<D>
{
friend A<D>;
};
int main()
{
A<B>::do_thing();
A<C>::do_thing();
A<D>::do_thing(); // This will not compile.
return (0);
}
This looks to me like right place to implement bridge pattern. Maybe this is what you are (unconsciously) willing to achieve. In short you specify an interface and its implementations, then call to your do_thing method in turn calls an implementation on a pointer to implementer class.
C++ example
first off: I have read and I know now that a virtual template member function is not (yet?) possible in C++. A workaround would be to make the class a template and then use the template-argument also in the member-function.
But in the context of OOP, I find that the below example would not be very "natural" if the class was actually a template. Please note that the code is actually not working, but the gcc-4.3.4 reports: error: templates may not be ‘virtual’
#include <iostream>
#include <vector>
class Animal {
public:
template< class AMOUNT >
virtual void eat( AMOUNT amount ) const {
std::cout << "I eat like a generic Animal." << std::endl;
}
virtual ~Animal() {
}
};
class Wolf : public Animal {
public:
template< class AMOUNT >
void eat( AMOUNT amount) const {
std::cout << "I eat like a wolf!" << std::endl;
}
virtual ~Wolf() {
}
};
class Fish : public Animal {
public:
template< class AMOUNT >
void eat( AMOUNT amount) const {
std::cout << "I eat like a fish!" << std::endl;
}
virtual ~Fish() {
}
};
class GoldFish : public Fish {
public:
template< class AMOUNT >
void eat( AMOUNT amount) const {
std::cout << "I eat like a goldfish!" << std::endl;
}
virtual ~GoldFish() {
}
};
class OtherAnimal : public Animal {
virtual ~OtherAnimal() {
}
};
int main() {
std::vector<Animal*> animals;
animals.push_back(new Animal());
animals.push_back(new Wolf());
animals.push_back(new Fish());
animals.push_back(new GoldFish());
animals.push_back(new OtherAnimal());
for (std::vector<Animal*>::const_iterator it = animals.begin(); it != animals.end(); ++it) {
(*it)->eat();
delete *it;
}
return 0;
}
So creating a "Fish< Amount > foo" is kind of strange. However, it seems desirable to me to provide an arbitrary amount of food to eat for each animal.
Thus, I am searching a solution about how to achieve something like
Fish bar;
bar.eat( SomeAmount food );
This becomes particularly useful when looking at the for-loop. One might like to feed a specific amount (FoodAmount) to all of the different animals (via eat() and bind1st() e.g.), it could not be done that easily, although I wound find this very inuitive (and thus to some extent "natural). While some might want to argue now that this is due to the "uniform"-character of a vector, I think/wish that it should be possible to achieve this and I really would like to know how, as this is puzzling me for quite some time now...
[EDIT]
To perhaps clarify the motivation behind my question, I want to program an Exporter-class and let different, more specialized classes derive from it. While the top-level Exporter-class is generally only for cosmetic/structural purpose, a GraphExporter-class is derived, that should again serve as a base-class for even more specialzed export. However, similar to the Animal-example, I would like to be able to define GraphExporter* even on specialized/derived classes (e.g. on SpecialGraphExplorer) but when calling "write( out_file )", it should call the appropriate member function for SpecialGraphExporter instead of GraphExporter::write( out_file).
Maybe this makes my situation and intentions clearer.
Best,
Shadow
After some thinking I recognized this as the classic multi-method requirement, i.e. a method that dispatches based on the runtime type of more than one parameter. Usual virtual functions are single dispatch in comparison (and they dispatch on the type of this only).
Refer to the following:
Andrei Alexandrescu has written (the seminal bits for C++?) on implementing multi-methods using generics in 'Modern C++ design'
Chapter 11: "Multimethods" - it implements basic multi-methods, making them logarithmic (using ordered typelists) and then going all the way to constant-time multi-methods. Quite powerful stuff !
A codeproject article that seems to have just such an implementation:
no use of type casts of any kind (dynamic, static, reinterpret, const or C-style)
no use of RTTI;
no use of preprocessor;
strong type safety;
separate compilation;
constant time of multimethod execution;
no dynamic memory allocation (via new or malloc) during multimethod call;
no use of nonstandard libraries;
only standard C++ features is used.
C++ Open Method Compiler, Peter Pirkelbauer, Yuriy Solodkyy, and Bjarne Stroustrup
The Loki Library has A MultipleDispatcher
Wikipedia has quite a nice simple write-up with examples on Multiple Dispatch in C++.
Here is the 'simple' approach from the wikipedia article for reference (the less simple approach scales better for larger number of derived types):
// Example using run time type comparison via dynamic_cast
struct Thing {
virtual void collideWith(Thing& other) = 0;
}
struct Asteroid : Thing {
void collideWith(Thing& other) {
// dynamic_cast to a pointer type returns NULL if the cast fails
// (dynamic_cast to a reference type would throw an exception on failure)
if (Asteroid* asteroid = dynamic_cast<Asteroid*>(&other)) {
// handle Asteroid-Asteroid collision
} else if (Spaceship* spaceship = dynamic_cast<Spaceship*>(&other)) {
// handle Asteroid-Spaceship collision
} else {
// default collision handling here
}
}
}
struct Spaceship : Thing {
void collideWith(Thing& other) {
if (Asteroid* asteroid = dynamic_cast<Asteroid*>(&other)) {
// handle Spaceship-Asteroid collision
} else if (Spaceship* spaceship = dynamic_cast<Spaceship*>(&other)) {
// handle Spaceship-Spaceship collision
} else {
// default collision handling here
}
}
}
Obviously, virtual member function templates are not allowed and could not be realized even theoretically. To build a base class' virtual table, there needs to be a finite number of virtual function-pointer entries. A function template would admit an indefinite amount of "overloads" (i.e. instantiations).
Theoretically-speaking, a language (like C++) could allow virtual member function templates if it had some mechanism to specify the actual (finite) list of instantiations. C++ does have that mechanism (i.e. explicit template instantiations), so I guess it could be possible to do this in a newer C++ standard (although I have no idea what trouble it would entail for compiler vendors to implement this feature). But, that's just a theoretical discussion, in practice, this is simply not allowed. The fact remains, you have to make the number of virtual functions finite (no templates allowed).
Of course, that doesn't mean that class template cannot have virtual functions, nor does it mean that virtual functions cannot call function templates. So, there are many solutions in that vein (like the Visitor pattern or other schemes).
One solution that, I think, serves your purpose (although it is hard to comprehend) elegantly is the following (which is basically a visitor pattern):
#include <iostream>
#include <vector>
struct Eater {
virtual void operator()(int amount) const = 0;
virtual void operator()(double amount) const = 0;
};
template <typename EaterType>
struct Eater_impl : Eater {
EaterType& data;
Eater_impl(EaterType& aData) : data(aData) { };
virtual void operator()(int amount) const { data.eat_impl(amount); };
virtual void operator()(double amount) const { data.eat_impl(amount); };
};
class Animal {
protected:
Animal(Eater& aEat) : eat(aEat) { };
public:
Eater& eat;
virtual ~Animal() { delete &eat; };
};
class Wolf : public Animal {
private:
template< class AMOUNT >
void eat_impl( AMOUNT amount) const {
std::cout << "I eat like a wolf!" << std::endl;
}
public:
friend struct Eater_impl<Wolf>;
Wolf() : Animal(*(new Eater_impl<Wolf>(*this))) { };
virtual ~Wolf() { };
};
class Fish : public Animal {
private:
template< class AMOUNT >
void eat_impl( AMOUNT amount) const {
std::cout << "I eat like a fish!" << std::endl;
}
public:
friend struct Eater_impl<Fish>;
Fish() : Animal(*(new Eater_impl<Fish>(*this))) { };
virtual ~Fish() { };
};
int main() {
std::vector<Animal*> animals;
animals.push_back(new Wolf());
animals.push_back(new Fish());
for (std::vector<Animal*>::const_iterator it = animals.begin(); it != animals.end(); ++it) {
(*it)->eat(int(0));
(*it)->eat(double(0.0));
delete *it;
};
return 0;
};
The above is a neat solution because it allows you to define a finite number of overloads that you want in one place only (in the Eater_impl class template) and all you need in the derived class is a function template (and possibly additional overloads, for special cases). There is, of course, a bit of overhead, but I guess that a bit more thought could be put into it to reduce the overhead (additional reference storage and dynamic allocation of Eater_impl). I guess, the curiously recurring template pattern could probably be employed somehow to this end.
I think the visitor pattern can be a solution.
UPDATE
I finished my example:
#include <iostream>
#include <vector>
#include <boost/shared_ptr.hpp>
class Animal;
class Wolf;
class Fish;
class Visitor
{
public:
virtual void visit(const Animal& p_animal) const = 0;
virtual void visit(const Wolf& p_animal) const = 0;
virtual void visit(const Fish& p_animal) const = 0;
};
template<class AMOUNT>
class AmountVisitor : public Visitor
{
public:
AmountVisitor(AMOUNT p_amount) : m_amount(p_amount) {}
virtual void visit(const Animal& p_animal) const
{
std::cout << "I eat like a generic Animal." << std::endl;
}
virtual void visit(const Wolf& p_animal) const
{
std::cout << "I eat like a wolf!" << std::endl;
}
virtual void visit(const Fish& p_animal) const
{
std::cout << "I eat like a fish!" << std::endl;
}
AMOUNT m_amount;
};
class Animal {
public:
virtual void Accept(const Visitor& p_visitor) const
{
p_visitor.visit(*this);
}
virtual ~Animal() {
}
};
class Wolf : public Animal {
public:
virtual void Accept(const Visitor& p_visitor) const
{
p_visitor.visit(*this);
}
};
class Fish : public Animal {
public:
virtual void Accept(const Visitor& p_visitor) const
{
p_visitor.visit(*this);
}
};
int main()
{
typedef boost::shared_ptr<Animal> TAnimal;
std::vector<TAnimal> animals;
animals.push_back(TAnimal(new Animal()));
animals.push_back(TAnimal(new Wolf()));
animals.push_back(TAnimal(new Fish()));
AmountVisitor<int> amount(10);
for (std::vector<TAnimal>::const_iterator it = animals.begin(); it != animals.end(); ++it) {
(*it)->Accept(amount);
}
return 0;
}
this prints:
I eat like a generic Animal.
I eat like a wolf!
I eat like a fish!
Per Mikael's post, I have made another offshoot, using the CRTP and following Eigen's style of using derived() for an explicit subclass reference:
// Adaptation of Visitor Pattern / CRTP from:
// http://stackoverflow.com/a/5872633/170413
#include <iostream>
using std::cout;
using std::endl;
class Base {
public:
virtual void tpl(int x) = 0;
virtual void tpl(double x) = 0;
};
// Generics for display
template<typename T>
struct trait {
static inline const char* name() { return "T"; }
};
template<>
struct trait<int> {
static inline const char* name() { return "int"; }
};
template<>
struct trait<double> {
static inline const char* name() { return "double"; }
};
// Use CRTP for dispatch
// Also specify base type to allow for multiple generations
template<typename BaseType, typename DerivedType>
class BaseImpl : public BaseType {
public:
void tpl(int x) override {
derived()->tpl_impl(x);
}
void tpl(double x) override {
derived()->tpl_impl(x);
}
private:
// Eigen-style
inline DerivedType* derived() {
return static_cast<DerivedType*>(this);
}
inline const DerivedType* derived() const {
return static_cast<const DerivedType*>(this);
}
};
// Have Child extend indirectly from Base
class Child : public BaseImpl<Base, Child> {
protected:
friend class BaseImpl<Base, Child>;
template<typename T>
void tpl_impl(T x) {
cout << "Child::tpl_impl<" << trait<T>::name() << ">(" << x << ")" << endl;
}
};
// Have SubChild extend indirectly from Child
class SubChild : public BaseImpl<Child, SubChild> {
protected:
friend class BaseImpl<Child, SubChild>;
template<typename T>
void tpl_impl(T x) {
cout << "SubChild::tpl_impl<" << trait<T>::name() << ">(" << x << ")" << endl;
}
};
template<typename BaseType>
void example(BaseType *p) {
p->tpl(2);
p->tpl(3.0);
}
int main() {
Child c;
SubChild sc;
// Polymorphism works for Base as base type
example<Base>(&c);
example<Base>(&sc);
// Polymorphism works for Child as base type
example<Child>(&sc);
return 0;
}
Output:
Child::tpl_impl<int>(2)
Child::tpl_impl<double>(3)
SubChild::tpl_impl<int>(2)
SubChild::tpl_impl<double>(3)
SubChild::tpl_impl<int>(2)
SubChild::tpl_impl<double>(3)
This snippet may be found in source here: repro:c808ef0:cpp_quick/virtual_template.cc
Virtual template function is not allowed. However you can use one OR the other here.
You could make an interface using virtual methods and implement your various animals in terms of having an eating interface. (i.e. PIMPL)
Less human intuitive would be having a non-member non-friend template function as a free function which could take templated const reference to any animal and make them eat accordingly.
For the record you don't need templates here. Pure virtual abstract method on the base class is enough to force and interface where all animals must eat and define how they do so with an override, providing a regular virtual would be enough to say all animals can eat but if they don't have a specific way then they can use this default way.
You can create a template class with virtual function, and implement the function in the derived class without using template in the follwing way:
a.h:
template <class T>
class A
{
public:
A() { qDebug() << "a"; }
virtual A* Func(T _template) { return new A;}
};
b.h:
class B : public A<int>
{
public:
B();
virtual A* Func(int _template) { return new B;}
};
and the function CTOR and call
A<int>* a1=new B;
int x=1;
a1->Func(x);
unfortunately i havn't found a way to create a virtual function with template parameters without declaring the class as a template and it template type on the dervied class
I have copied your code and modified it, so now it should work exactly as you want:
#include <iostream>
#include <vector>
//defined new enum type
enum AnimalEnum
{
animal,
wolf,
fish,
goldfish,
other
};
//forward declarations
class Wolf;
class Fish;
class GoldFish;
class OtherAnimal;
class Animal {
private:
AnimalEnum who_really_am_I;
void* animal_ptr;
public:
//declared new constructors overloads for each type of animal
Animal(const Animal&);
Animal(const Wolf&);
Animal(const Fish&);
Animal(const GoldFish&);
Animal(const OtherAnimal&);
template< class AMOUNT >
/*removed the virtual keyword*/ void eat( AMOUNT amount ) const {
switch (this->who_really_am_I)
{
case AnimalEnum::other: //You defined OtherAnimal so that it doesn't override the eat action, so it will uses it's Animal's eat
case AnimalEnum::animal: std::cout << "I eat like a generic Animal." << std::endl; break;
case AnimalEnum::wolf: ((Wolf*)this->animal_ptr)->eat(amount); break;
case AnimalEnum::fish: ((Fish*)this->animal_ptr)->eat(amount); break;
case AnimalEnum::goldfish: ((GoldFish*)this->animal_ptr)->eat(amount) break;
}
}
void DeleteMemory() { delete this->animal_ptr; }
virtual ~Animal() {
//there you can choose if whether or not to delete "animal_ptr" here if you want or not
}
};
class Wolf : public Animal {
public:
template< class AMOUNT >
void eat( AMOUNT amount) const {
std::cout << "I eat like a wolf!" << std::endl;
}
virtual ~Wolf() {
}
};
class Fish : public Animal {
public:
template< class AMOUNT >
void eat( AMOUNT amount) const {
std::cout << "I eat like a fish!" << std::endl;
}
virtual ~Fish() {
}
};
class GoldFish : public Fish {
public:
template< class AMOUNT >
void eat( AMOUNT amount) const {
std::cout << "I eat like a goldfish!" << std::endl;
}
virtual ~GoldFish() {
}
};
class OtherAnimal : public Animal {
//OtherAnimal constructors must be defined here as Animal's constructors
OtherAnimal(const Animal& a) : Animal(a) {}
OtherAnimal(const Wolf& w) : Animal(w) {}
OtherAnimal(const Fish& f) : Animal(f) {}
OtherAnimal(const GoldFish& g) : Animal(g) {}
OtherAnimal(const OtherAnimal& o) : Animal(o) {}
virtual ~OtherAnimal() {
}
};
//OtherAnimal will be useful only if it has it's own actions and members, because if not, typedef Animal OtherAnimal or using OtherAnimal = Animal can be used, and it can be removed from above declarations and below definitions
//Here are the definitions of Animal constructors that were declared above/before:
Animal::Animal(const Animal& a) : who_really_am_I(AnimalEnum::animal), animal_ptr(nullptr) {}
Animal::Animal(const Wolf& w) : who_really_am_I(AnimalEnum::wolf), animal_ptr(new Wolf(w)) {}
Animal::Animal(const Fish& f) : who_really_am_I(AnimalEnum::fish), animal_ptr(new Fish(f)) {}
Animal::Animal(const GoldFish& g) : who_really_am_I(AnimalEnum::goldfish), animal_ptr(new GoldFish(g)) {}
Animal::Animal(const OtherAnimal& o) :
who_really_am_I(AnimalEnum::other), animal_ptr(new OtherAnimal(o)) {}
int main() {
std::vector<Animal> animals;
animals.push_back(Animal());
animals.push_back(Wolf()); //Wolf is converted to Animal via constructor
animals.push_back(Fish()); //Fish is converted to Animal via constructor
animals.push_back(GoldFish()); //GoldFish is converted to Animal via constructor
animals.push_back(OtherAnimal()); //OtherAnimal is converted to Animal via constructor
for (std::vector<Animal>::const_iterator it = animals.begin(); it != animals.end(); ++it) {
it->eat(); //this is Animal's eat that invokes other animals eat
//delete *it; Now it should be:
it->DeleteMemory();
}
animals.clear(); //All animals have been killed, and we don't want full vector of dead animals.
return 0;
}
In you scenario, you are trying to mix compile time polymorphism with runtime polymorphism, but it cannot be done in this "direction".
Essential, your AMOUNT template argument represents an expected interface for the type to implement based on the union of all the operations each implementation of eat uses. If you where to create an abstract type that declared each of those operations making them virtual where needed, then you could call eat with different types (that derived from your AMOUNT interface). And it would behave as expected.
I don't work with templates, but I think:
(1) You cannot use templates inside a class, templates are more like global types or global variables.
(2) In O.O.P., the same problem you present, and that you are trying to solve by using templates, can be solved by using inheritance.
Classes work similar to templates, you can extended by adding new things, or replace things of classes with pointers, pointers to objects (A.K.A. "references") and overriding virtual functions.
#include <iostream>
struct Animal {
virtual void eat(int amount ) {
std::cout << "I eat like a generic Animal." << std::endl;
}
virtual ~Animal() { }
};
#if 0
// example 1
struct Wolf : Animal {
virtual void eat(int amount) {
std::cout << "I eat like a wolf!" << std::endl;
}
};
struct Fish : Animal {
virtual void eat(int amount) {
std::cout << "I eat like a fish!" << std::endl;
}
};
#else
// example 2
struct AnimalFood {
virtual int readAmount() { return 5; }
virtual void showName() {
std::cout << "I'm generic animal food" << std::endl;
}
};
struct PredatorFood : AnimalFood {
virtual int readAmount() { return 500; }
virtual void showName() {
std::cout << "I'm food for a predator" << std::endl;
}
};
struct Fish : Animal {
virtual void eat(AnimalFood* aFood) {
if (aFood->readAmount() < 50) {
std::cout << "OK food, vitamines: " << aFood->readAmount() << std::endl;
} else {
std::cout << "too much food, vitamines: " << aFood->readAmount() << std::endl;
}
}
};
struct Shark : Fish {
virtual void eat(AnimalFood* aFood) {
if (aFood->readAmount() < 250) {
std::cout << "too litle food for a shark, Im very hungry, vitamines: " << aFood->readAmount() << std::endl;
} else {
std::cout << "OK, vitamines: " << aFood->readAmount() << std::endl;
}
}
};
struct Wolf : Fish {
virtual void eat(AnimalFood* aFood) {
if (aFood->readAmount() < 150) {
std::cout << "too litle food for a wolf, Im very hungry, vitamines: " << aFood->readAmount() << std::endl;
} else {
std::cout << "OK, vitamines: " << aFood->readAmount() << std::endl;
}
}
};
#endif
int main() {
// find animals
Wolf* loneWolf = new Wolf();
Fish* goldenFish = new Fish();
Shark* sharky = new Shark();
// prepare food
AnimalFood* genericFood = new AnimalFood();
PredatorFood* bigAnimalFood = new PredatorFood();
// give food to animals
loneWolf->eat(genericFood);
loneWolf->eat(bigAnimalFood);
goldenFish->eat(genericFood);
goldenFish->eat(bigAnimalFood);
sharky->eat(genericFood);
sharky->eat(bigAnimalFood);
delete bigAnimalFood;
delete genericFood;
delete sharky;
delete goldenFish;
delete loneWolf;
}
Cheers.