I want to make a class with a member function that takes a reference to another class, where both classes are derived from abstract classes. I get a compiler error that the class Container is abstract because it doesn't implement addElem().
class Ielem
{
public:
virtual void action() = 0;
};
class Elem: public Ielem
{
public:
void action() {};
void extra() {};
};
class Icontainer
{
public:
virtual void addElem(Ielem &elem) = 0;
};
class Container: public Icontainer
{
public:
void addElem(Elem &elem) { elem.extra(); };
};
int main(int argc, char* argv[])
{
Elem e;
Container c;
c.addElem(e);
return 0;
}
It seems like this ought to work, because any reference to an Elem is also a reference to an Ielem. It compiles if I make Container::addElem take a reference to an Ielem. But then Container::addElem() can't call Elem::extra() unless I use dynamic_cast, which isn't available on the embedded compiler I'm using, or a regular cast, which isn't type safe.
Suggestions?
It's the wrong way round: the base class Icontainer specifies that addElem can take any Ielem object as an argument, but in your derived class you accept only Elem. This is a "narrower" type, so the contract "I'll accept any Ielem you throw at me" specified in the base class is violated.
I think templates would be the solution here. You don't even need the base classes anymore. Something like this:
class Elem
{
public:
void action() {};
void extra() {};
};
template<typename ElemType>
class Container
{
public:
void addElem(ElemType &elem) { elem.extra(); };
};
int main(int argc, char* argv[])
{
Elem e;
Container<Elem> c;
c.addElem(e);
return 0;
}
As a bonus, you can now use Container with any type that has an extra() function, and it will just work.
The problem is simply that your virtual method doesn't have the same signature as the concrete method which is intended to overload it; so the compiler sees it as a different function entirely and complains because you haven't implemented void addElem(Ielem &elem). This is one solution, which you probably don't want--
class Icontainer
{
public:
virtual void addElem(Elem &elem) = 0; //Ielem -> Elem
};
It depends on all your other constraints but I think what I would do--and what seems to conform to general design guidelines, e.g. Sutter & Alexandreascu, would be to create an intermediate abstract class with the full interface--
class Melem: public Ielem
{
public:
// void action() {}; //Already have this form Ielem
void extra() = 0;
};
and then
class Icontainer
{
public:
virtual void addElem(Melem &elem) = 0;
};
class Container: public Icontainer
{
public:
void addElem(Melem &elem) { elem.extra(); };
//*Now* we're implementing Icontainer::addElem
};
Related
I have an example like the one below in C++ where I receive a pointer to base class, exampleParent, and would like to cast it to a pointer to the inherited class example (in reality I just want to call a function on example) . The caveat is that the inherited class is templated. In the example below, I know the template is of type int so there is no problem. In general, what would be a good way to do this if I am not aware before hand the type of the template?
class exampleParent{};
template<typename P>
class example: public exampleParent
{
public:
int do_something() const
{
std::cout<<"I am doing something"<<std::endl;
return 0;
}
};
boost::shared_ptr<const exampleParent> getPtr()
{
return boost::make_shared<const example<int>>();
}
int main()
{
boost::shared_ptr<const exampleParent> example = getPtr();
auto example_ptr = boost::dynamic_pointer_cast<const example<int>>(example);
return example_ptr-> do_something();
}
One solution I propose is to change the code to something like this:
class exampleParent{};
class something_interface: public exampleParent
{
public:
virtual int do_something() const = 0 ;
};
template<typename P>
class example: public something_interface
{
public:
int do_something() const override
{
std::cout<<"I am doing something"<<std::end;
return 0;
}
};
boost::shared_ptr<const exampleParent> getPtr()
{
return boost::make_shared<const example<int>>();
}
int main()
{
boost::shared_ptr<const exampleParent> example = getPtr();
auto example_ptr = boost::dynamic_cast<const something_interface>(example);
return example_ptr->do_something();
}
This would work, but it feels a bit of a hack: something_interface should not really exist, as it has no object oriented interpretation in itself.
Any help would be appreciated!
If you can make exampleParent an abstract class (if you can modify that class at all), that would be the best:
class exampleParent
{
public:
virtual ~exampleParent() = default;
virtual int do_something() const = 0;
};
template<typename P>
class example: public exampleParent
{
public:
int do_something() const override
{
std::cout<<"I am doing something"<<std::endl;
return 0;
}
};
Then you don't need a cast to invoke that method.
If you cannot touch this exampleParent class, go on with the intermediate one as you proposed, but remember to actually inherit exampleParent and don't throw exception, just make the method pure virtual:
class intermediate: public exampleParent
{
public:
~intermediate() override = default;
virtual int do_something() const = 0;
};
Otherwise the only way is to do dynamic_pointer_cast for all possible types and check the cast result, because different instances of template class are just different types in general. Of course it doesn't make sense if there is infinite number of possible template parameters P.
Is there a way to force implementation of a method in a child class where the implementation will have a different signature for each derived class?
I know I can do this, using pure virtual:
class Base {
public:
virtual void getValue(string& s) = 0;
}
class Derived : public Base {
public:
void getValue(string& s);
}
Above, pure virtual getValue in the base class forces the derived class to implement getValue. But what I really want to do is something like this: Force each derived class to implement getValue() but each with a different signature:
class Base {
public:
void getValue() = 0;
}
class Derived_A : public Base {
public:
void getValue(string& s);
}
class Derived_B : public Base {
public:
void getValue(int *j);
}
The problem with the above is that, due to name mangling, each signature is effectively a different function, and thus Derived_A and Derived_B inherit getValue() = 0 and the compiler thinks that they also are abstract.
I've been playing around with some different ways to do this, but it appears to me there is no way to do it. I'm thinking I should simply not declare getValue in the Base class and then just make sure each derived class implements their version of it.
If use of CRTP would work for you, you can use:
#include <string>
template <typename TypeSelector>
class Base {
public:
using type = typename TypeSelector::type;
virtual void getValue(type t) = 0;
};
struct TypeSelector_A {
using type = std::string&;
};
class Derived_A : public Base<TypeSelector_A> {
public:
void getValue(std::string& s) { /* Add real implementation */ }
};
struct TypeSelector_B {
using type = int*;
};
class Derived_B : public Base<TypeSelector_B> {
public:
void getValue(int* j) { /* Add real implementation */ }
};
int main()
{
Derived_A a;
Derived_B b;
}
But what I really want to do is something like this: Force each derived class to implement getValue() but each with a different signature
The whole point of having virtual function (abstract or not) is that you can use it with pointer or reference to the base class which means you would use signature of the function from the base class. With that having what you want is completely useless. What you want can be implemented by returning std::variant or std::any with every virtual function in tree so keeping signature the same.
You should think how would you use such concept if it would be possible. If you think somethink like this:
void foo( Base *b ) {
if( auto *d = dynamic_cast<Derived_A *>( b ) ) {
std::string str;
d->getValue( str );
...
}
if( auto *d = dynamic_cast<Derived_B *>( b ) ) {
int i = 0;
d->getValue( &i );
...
}
}
then getValue() does not need to be virtual, you only need vritual destrictor in Base. But this is considered bad design.
template <class CollectionItem>
class Collection
{
void A();
// Many other utility functions
}
class ICollection
{
virtual void B() = 0;
}
class Base : public Collection<BaseItem>, public IBase
{
virtual void B();
}
Is there any way of offering Collection functions via ICollection interface without wrapping all the functions in Base class? ICollection : public Collection<CollectionItem> is not an option.
Bounty Update:
OK, so the original idea was to have Interface to all Collection classes. Before we continue, every CollectionItem also has Interface, let's call it ICollectionItem and ICollection only knows about ICollectionItem.
So what I did was create another template class as Interface to Collection template class - ICollection (pure virtual) accepting ICollectionItem(s). Collection class inherits this interface.
Every Collection class (inheriting Collection<CollectionItem> class) would also inherit it's Interface Collection class. That Interface then virtual inherits ICollection<ICollectionItem>. I'll just post the code :)
Here is the code:
template <class ICollectionItem>
class ICollection
{
public:
virtual const ICollectionItem* At(const int idx) = 0;
};
template <class CollectionItem, class ICollectionItem>
class Collection
: public ICollection,
public virtual ICollection<ICollectionItem> // Weak point
{
private:
List<CollectionItem*> fContainer;
public:
Collection(void) {}
virtual ~Collection() {}
virtual const ICollectionItem* At(const int idx); // Casting GetAt result
virtual const TCollectionItem& GetAt(const int idx) const
virtual ListIterator<TCollectionItem> >* GetIterator(void) const;
virtual ListIterator<ICollectionItem> >* Iterator(void) const; // Weak point
}
Example usage:
class IBaseItem
{
public:
virtual int Number() = 0;
{
class BaseItem
: public IBaseItem
{
public:
virtual int Number();
void SetNumber(int value);
}
class IBase
: public virtual ICollection<IBaseItem>
{
public:
virtual IBaseItem* ItemByName(String name) = 0;
virtual ~IBase() {}
}
class Base
: public Collection<BaseItem, IBaseItem>,
public IBase
{
public:
BaseItem* GetItemByName(String name);
virtual IBaseItem* ItemByName(String name);
}
Weak points:
First is at using virtual inheritance ... lots written about it, not much to talk about, or is it?
Unable to access Iterator using ICollection interface. See ListIterator function, only first one can be implemented, the second one would require some kind of new List of IBaseItem. I decided to live with that and just use for loop.
Even tho I somehow managed to get what I wanted (With wrapping and casting), I would still like to hear an second opinion. I don't like using virtual inheritance, specially in such delicate situations - using Collections for application Base creation.
I can not see any other solution than calling some Collection method in Base implementation of IBase virtual methods.
class Base : public Collection<BaseItem>, public IBase
{
virtual void B()
{
A();
}
}
You say, and I quote:
I want to call Collection functions using IBase pointer
I really don't see what is to be done here besides dynamic_cast. It does exactly what you want it to do.
void fun(IBase * base) {
auto * coll = dynamic_cast<Collection<BaseItem>*>(base);
if (coll) {
coll->A();
}
}
Your Collection class must have a virtual destructor.
You can, of course, offer a templated version, if you'd need different baseitems in different, scenarios for some reasons. This has bad code smell and I think your architecture is bad at this point, but oh well.
template <typename T> void fun(IBase * base) {
auto * coll = dynamic_cast<Collection<T>*>(base);
if (coll) {
coll->A();
}
}
void test(IBase * p) {
fun<BaseItem5>(p);
}
If you have some other specific scenario in mind, please edit your question to say what you mean.
Hmm...So you wanna to reuse the Collection class's utility functions, and you want to design a class which will implement an interface defined by IBase. As you mentioned above,"wrapping all the functions in Base class" is a way to offer Collection functions.
(1) Via inheritance,derived class has a good knowledge of Collection
class Derived:public Collection<DerivedType>,public IBase{};
or
template <typename T>
class Derived:public Collection<T>,public IBase{};
(2) Via inheritance,derived class knows little about Collection,but through IBase
class IBase : public Collection<BaseItem>{};
class Derived:public IBase{};
By (1),If you want to call Collection functions using IBase pointer,you have to wrap the functions.
By (2), any Derived instance is " a kind of " IBase which is "a kind of " Collection. So you can use IBase pointer to call Collection functions.
So,the key point is that the objects pointed by the IBase pointer should have the method you want to call.Wrap it or inherit it. I can not see any other solution than these two ways.
Edit: the idea is refined based on your example:
Here is an idea:
//generic interface can be kept as it is
template <class ICollectionItem>
class ICollection
{
public:
virtual const ICollectionItem* At(const int idx) = 0;
};
class Empty
{
};
template <class CollectionItem , class BaseClass = Empty>
class GenericCollection
: public BaseClass
{
public:
const CollectionItem* At(const int idx);
// At and ItemByName are standard functions for a collection
CollectionItem* ItemByName(String name);
//note that here nothing has to be declared as virtual
};
//example usage:
class IBase
: public virtual ICollection<IBaseItem>
{
public:
virtual IBaseItem* ItemByName(String name) = 0;
virtual ~IBase() {}
};
class Base
: public GenericCollection<BaseItem, IBase >
{
public:
//nothing to be implemented here, all functions are implemented in GenericCollection and defined as virtual in IBase
//The definition of the functions has to be the same:
};
In collection you can implement whatever and in the interface you can define what ever you want to be virtual from your collection. The only thing is that you need to have some standard in naming convention for functions.
Hope this helps,
Raxvan.
From your comments in another answer, it seems you want a collection of interfaces, and an implementation of this interface. The simplest I can advise you is the following:
template<typename T>
class ICollection
{
public:
virtual iterator<T>* begin() const = 0;
};
template<typename T, typename TBase>
class Collection : public ICollection<TBase>
{
public:
iterator_impl<T>* begin() const { return whatever; }
};
Example:
class IItem {};
class Item : public IItem {};
class Base : public Collection<Item, IItem> {};
old answer:
Is there any way of offering Collection functions via IBase interface without wrapping all the functions in Base class ?
If I understood your problem, you want to use it like this:
void myfunc()
{
// ...
IBase* obj = ...;
obj->A();
obj->B();
}
I think here is a misunderstanding here: if you want A() to be callable from an IBase, then you have to add it to Ibase declaration.
If you want to use the Collection functions on an object, then you should cast this object to a Collection, via dynamic_cast for example.
Furthermore, if you have such a funcion:
void fun(IBase* base) { /* ... */ }
you cannot cast to a Collection*, since there are no relationship between these two classes, unless you have another way to be sure base is a Collection:
void fun(IBase* base)
{
if(base && base->isABaseItemCollection())
{
// Valid, since the real type was checked before
Collection* collection = (Collection*)base;
// ...
}
}
On a side note: you can generate bases almost automatically:
template
class Base : public Collection, public U {};
typedef Base BaseCollection;
According to comment/chat:
You have something like:
class IAnimal { /*...*/ };
class Cat : public IAnimal { /*...*/ };
class Dog : public IAnimal { /*...*/ };
class Cats
{
std::vector<Cat*> cats;
public:
Cat* at(size_t index) { return cats[index]; }
/*...*/
};
class Dogs
{
std::vector<Dog*> dogs;
public:
Dog* at(size_t index) { return dogs[index]; }
/*...*/
};
And you want to factorize some code using something like
class IAnimals
{
public:
std::vector<IAnimals*> animals; // or getter/setter which works with IAnimals.
/* some common factorized code */
};
// And so
class Cats : public IAnimals { /**/ };
class Dogs : public IAnimals { /**/ };
I propose, instead of creating class IAnimals, to use template functions as:
template <typename TAnimals>
void foo(TAnimals& animals)
{
Ianimals* animal = animals.at(42);
// ...
animal->eat(food);
// ...
}
You have to give compatible "interface" (names) to the type used in template.
Maybe you could have an operator() in IBase that would be delegated to Base?
class CollectionBase {};
template <class Item> class Collection: public CollectionBase {};
class IBase
{
public:
virtual CollectionBase* operator()() = 0;
};
class Base : public Collection<BaseItem>, public IBase
{
public:
virtual Collection<BaseItem>* operator()() { return this; }
};
I'm trying to create a class that serves as a base object, which will then be sub-classed (=implemented) to serve various purposes.
I want to define one or more pure virtual functions, so that however subclasses the base class, is required and does not forget to implement them.
There is one caveat, the pure virtual function's signature includes the type of the base object. Once sub-classed, the function definition doesn't match the base classes definition anymore of course. E.g.:
class BaseItem
{
public:
virtual std::string getDifferences(const BaseItem& item) = 0;
}
So, in the derived class I'd like to do:
class DerivedClass : public BaseItem
{
public:
virtual std::string getDifferences(const DerivedClass& item) = 0;
private:
std::string derivedItemCustomObject;
}
which of course the compiler won't accept. I could make it a BaseItem of course, but then I can't utilize any objects in the derived class.
Do I have to use casting to accomplish this?
Please let me know if my intent/question is not clear.
There is NO need to change the function signature. Look at following:
class BaseItem
{public:
virtual std::string getDifferences(const BaseItem& item) = 0;
};
class DerivedClass : public BaseItem
{public:
virtual std::string getDifferences(const BaseItem& item) // keep it as it's
{
const DerivedClass& derivedItem = static_cast<const DerivedClass&>(item);
}
};
Can use static_cast<> without any fear because, DerivedClass::getDifferences() is called only for DerivedClass object. To illustrate,
BaseItem *p = new DerivedClass;
DerivedClass obj;
p->getDifferences(obj); // this always invoke DerivedClass::getDifferences
If you worry that sometime you might end up passing any other derived class object as an argument to the method, then use dynamic_cast<> instead and throw exception if that casting fails.
It's unclear what you're trying to achieve. Suppose that the compiler allowed you to do this (or you do this by the means of a cast), then it would open the following hole in the type system:
class BaseItem
{
public:
virtual std::string getDifferences(const BaseItem& item) = 0;
};
class DerivedClass : public BaseItem
{
public:
virtual std::string getDifferences(const DerivedClass& item)
{
item.f();
// ...
}
void f() const {}
};
class DerivedClass2 : public BaseItem
{
public:
virtual std::string getDifferences(const DerivedClass2& item) { ... }
};
void g()
{
BaseItem* x = new DerivedClass;
// oops, calls DerivedClass::f on an instance of DerivedClass2
x->getDifferences(DerivedClass2());
}
Your design is probably wrong.
I assume that the compiler accept but DerivedClass::getDifferences doesn't override BaseItem::getDifferences. Here is a way to achieve what you apparently want
template <typename T>
class DerivedHelper: public BaseItem {
public:
virtual std::string getDifferences(const BaseItem& item) {
getDifferences(dynamic_cast<const T&>(item));
}
virtual std::string getDifferences(const T& item) = 0;
};
class DerivedClass : public DerivedHelper<DerivedClass>
{
public:
// not more needed but providing it will hide getDifferences(const BaseItem& item)
// helping to statically catch some cases where a bad argument type is used.
virtual std::string getDifferences(const DerivedClass& item) = 0;
private:
std::string derivedItemCustomObject;
};
but be aware that there is a runtime check which will throw exceptions if the argument isn't of the correct class.
One way to accomplish this is to use a template and have the parameter be the type of the derived type
template <typename T>
class BaseItem {
public:
virtual std::string getDifferences(const T& item) = 0;
};
class DerivedClass : public BaseItem<DerivedClass> {
public:
virtual std::string getDifferences(const DerivedClass& item) {
// Implement it here
}
};
You should use cast from BaseItem to DerivedClass + runtime check if given BaseItem is a DerivedClass instance.
Suppose I have the following classes:
class BaseObject {
public:
virtual int getSomeCommonProperty();
};
class Object1: public BaseObject {
public:
virtual int getSomeCommonProperty(); // optional
int getSomeSpecificProperty();
};
class BaseCollection {
public:
virtual void someCommonTask();
};
class Collection1: public BaseCollection {
public:
virtual void someCommonTask(); // optional
void someSpecificTask();
};
Each collection, derived from BaseCollection, deals with a specific object type (and only one type). But BaseCollection should be able to perform some tasks that are common to all objects, using only common object properties in BaseObject.
Currently, I have potentially three solutions in mind:
1) Store the objects list in BaseCollection, such as:
class BaseCollection {
vector<BaseObject*> objects;
};
The problem with this solution is that when I need to perform object-specific task in Collection1, I need a dynamic_cast<>, because I don't want to use virtual inherance for specific properties, applying to only one type of object. Considering that dynamic_cast<> could potentially get called millions of time per second, this seems an issue for a performance critical application.
2) Store the objects list in Collection1, such as:
class Collection1: public BaseCollection {
vector<Object1*> objects;
}
But then I need some way to access this object list in BaseCollection, to be able to perform some common tasks on them, ideally through an iterator. I would need to create a function that return a vector for the BaseCollection, but again, this does not seem very efficient, because the only way to do that is to create a new vector (potentially containing thousands of objects)...
3) Store the objects list in BaseCollection AND Collection1:
class BaseCollection {
public:
void someCommonTask(); // Use baseObjects
virtual void addObject() = 0;
protected:
vector<BaseObject*> baseObjects;
};
class Collection1: public BaseCollection {
vector<Object1*> objects;
public:
virtual void addObject() {
Object1* obj = new Object1;
objects.push_back(obj);
baseObjects.push_back(obj);
}
void someSpecificTask(); // Use objects, no need of dynamic_cast<>
}
Where the two lists actually contain the same objects. Is that as ugly as it sounds like?
I am looking for the right/correct/best design pattern for this type of problem and none of the 3 solutions exposed above really satisfies me...
Maybe it is possible to solve that problem with templates, but then I don't see a way to store a list of polymorphic collections like this:
vector<BaseCollection*> collections;
You can store all your objects of base and derived classes in one collection through the base class (smart) pointer. Using visitor design pattern and double dispatch mechanism you can call a function only on objects of a specific type without having to expose that function in the base class interface. For example:
#include <boost/intrusive_ptr.hpp>
#include <boost/bind.hpp>
#include <vector>
#include <algorithm>
#include <stdio.h>
struct Visitor { // Visitor design patter
virtual void visit(struct BaseObject&) {}
virtual void visit(struct Object1&) {}
};
struct BaseObject {
unsigned ref_count_; // intrusive_ptr support
BaseObject() : ref_count_() {}
virtual ~BaseObject() {}
virtual void accept(Visitor& v) { v.visit(*this); } // Visitor's double dispatch
virtual void getSomeCommonProperty() { printf("%s\n", __PRETTY_FUNCTION__); }
};
void intrusive_ptr_add_ref(BaseObject* p) { // intrusive_ptr support
++p->ref_count_;
}
void intrusive_ptr_release(BaseObject* p) { // intrusive_ptr support
if(!--p->ref_count_)
delete p;
}
struct Object1 : BaseObject {
virtual void accept(Visitor& v) { v.visit(*this); } // Visitor's double dispatch
virtual void getSomeCommonProperty() { printf("%s\n", __PRETTY_FUNCTION__); }
void getSomeSpecificProperty() { printf("%s\n", __PRETTY_FUNCTION__); }
};
template<class T, class Functor>
struct FunctorVisitor : Visitor {
Functor f_;
FunctorVisitor(Functor f) : f_(f) {}
void visit(T& t) { f_(t); } // apply to T objects only
template<class P> void operator()(P const& p) { p->accept(*this); }
};
template<class T, class Functor>
FunctorVisitor<T, Functor> apply_to(Functor f)
{
return FunctorVisitor<T, Functor>(f);
}
int main()
{
typedef boost::intrusive_ptr<BaseObject> BaseObjectPtr;
typedef std::vector<BaseObjectPtr> Objects;
Objects objects;
objects.push_back(BaseObjectPtr(new BaseObject));
objects.push_back(BaseObjectPtr(new Object1));
for_each(
objects.begin()
, objects.end()
, boost::bind(&BaseObject::getSomeCommonProperty, _1)
);
for_each(
objects.begin()
, objects.end()
, apply_to<BaseObject>(boost::bind(&BaseObject::getSomeCommonProperty, _1))
);
for_each(
objects.begin()
, objects.end()
, apply_to<Object1>(boost::bind(&Object1::getSomeSpecificProperty, _1))
);
}
Output:
$ ./test
virtual void BaseObject::getSomeCommonProperty()
virtual void Object1::getSomeCommonProperty()
virtual void BaseObject::getSomeCommonProperty()
void Object1::getSomeSpecificProperty()
I think you should go for option 1 but use a static cast instead. After all the derived collection knows the type of the member variable for sure.
This answer explains it very well.
Id use nested adapter as in below example. You have to specialize it for every class you want to do a fancy update
!The example has memory leak - allocated A, B, Q objects are not deleted!
#include <iostream>
#include <vector>
#include <algorithm>
class Q
{
public:
virtual void Foo()
{
std::cout << "Q::Foo()" << std::endl;
}
};
class A
{
public:
virtual void Foo()
{
std::cout << "A::Foo()" << std::endl;
}
};
class B : public A
{
public:
virtual void Foo()
{
std::cout << "B::Foo()" << std::endl;
}
virtual void BFoo()
{
std::cout << "B::BFoo()" << std::endl;
}
};
template <typename ElementType>
class C
{
public:
template <typename T>
void add(T* ptr){m_Collection.push_back(std::unique_ptr<Adapter>(new ConcreteAdapter<T>(ptr)));}
void updateAll()
{
std::for_each(m_Collection.begin(), m_Collection.end(), [&](std::unique_ptr<Adapter> &adapter)->void{adapter->update();});
}
private:
class Adapter
{
public:
virtual ElementType* get() = 0;
virtual void update(){get()->Foo();}
};
template <typename T>
class ConcreteAdapter : public Adapter
{
public:
ConcreteAdapter(T* ptr) : m_Ptr(ptr){}
virtual T* get(){return m_Ptr;}
protected:
T* m_Ptr;
};
template <>
class ConcreteAdapter<B> : public Adapter
{
public:
ConcreteAdapter(B* ptr) : m_Ptr(ptr){}
virtual B* get(){return m_Ptr;}
virtual void update()
{
get()->Foo();
get()->BFoo();
}
private:
B* m_Ptr;
};
std::vector<std::unique_ptr<Adapter>> m_Collection;
};
int main()
{
C<A> c;
c.add(new A());
c.add(new B());
//c.add(new Q()); //error - correct
c.updateAll();
return 0;
}
Maybe this will do the trick here ?
class CollectionManipulator {
public:
void someCommonTask(BaseCollection& coll) {
for(unsigned int i = 0; i < coll.size(); i++)
someCommonTask(coll.getObj(i));
}
private:
void someCommonTask(BaseObject*); // Use baseObjects
};
class BaseCollection {
friend class CollectionManipulator;
private:
virtual BaseObject* getObj(unsigned int) = 0;
virtual unsigned int size() const = 0;
};
class Collection1 : public BaseCollection {
vector<Object1*> objects;
public:
virtual void addObject() {
Object1* obj = new Object1;
objects.push_back(obj);
baseObjects.push_back(obj);
}
void someSpecificTask(); // Use objects, no need of dynamic_cast<>
private:
BaseObject* getObj(unsigned int value) {
return object[value];
}
unsigned int size() const {
return objects.size();
}
}
If you want abstract your container in Collection1 (like using list instead using vector), to use it in Manipulator, create an abstract iterator...
I think the solution should be a mix of factory method pattern and template method pattern. Take a look at those to refine your design.
Edit: Here is a sample code. GenericProduct is the BaseObject, it provides two methods, one that is general (though it could be overridden), and a specific method which does nothing, it is not a pure virtual so this class can be instantiated. SpecificProduct is a subclass, which implements the specific method in some way.
Now, Factory class is an abstract class that defines an interface for creating specific products by specific factories, it defines a pure virtual method createProduct which creates the product. Two concrete factories are created GenericFactory and SpecificFactory which create specific products.
Finally, the Consumer abstract class (which corresponds to BaseCollection in your code), it defines a pure virtual method for creating a factory createFactory in order to force subclasses to create their own concrete factories (and hence, the correct products). The class also define a method fillArray (prototype pattern) to fill the array with products created by the factory.
#include <iostream>
#include <vector>
using namespace std;
class GenericProduct{
public:
virtual void getSomeCommonProperty()
{
cout<<"Common Property\n";
}
virtual void getSomeSpecificProperty()
{
cout<<"Generic Has Nothing Specific\n";
}
};
class SpecificProduct : public GenericProduct{
public:
virtual void getSomeSpecificProperty()
{
cout<<"Specific Product Has a Specific Property\n";
}
};
class Factory
{
public:
virtual GenericProduct* createProduct() = 0;
};
class GenericFactory : public Factory
{
public:
virtual GenericProduct* createProduct()
{
return new GenericProduct();
}
};
class SpecificFactory : public Factory
{
public:
virtual GenericProduct* createProduct()
{
return new SpecificProduct();
}
};
class Consumer
{
protected:
vector<GenericProduct*> gp;
Factory* factory;
protected:
virtual void createFactory() = 0;
public:
void fillArray()
{
createFactory();
for(int i=0; i<10; i++)
{
gp.push_back(factory->createProduct());
}
}
virtual void someCommonTask()
{
cout<<"Performaing a Common Task ...\n";
for(int i=0; i<10; i++)
{
gp[i]->getSomeCommonProperty();
}
}
virtual void someSpecificTask()
{
cout<<"Performaing a Specific Task ...\n";
for(int i=0; i<10; i++)
{
gp[i]->getSomeSpecificProperty();
}
}
};
class GenericConsumer : public Consumer
{
virtual void createFactory()
{
factory = new GenericFactory();
}
};
class SpecificConsumer : public Consumer
{
virtual void createFactory()
{
factory = new SpecificFactory();
}
};
int main()
{
Consumer* c = new GenericConsumer();
c->fillArray();
c->someCommonTask();
return 0;
}