2

Note: This is almost a duplicate of this entry: Abstract classes and Pointers

I need to create a vector of virtual classes. Here the idea:

#include <vector>
using namespace std;

class VirtualFoo {
protected:
    VirtualFoo();
    virtual ~VirtualFoo();
public:
    virtual void doStuff()=0;
};

class ConcreteFoo: public VirtualFoo {
public:
    ConcreteFoo(double a);
    virtual ~ConcreteFoo();
    void doStuff();
private:
    double a;
};

class Foo {
public:
    Foo(std::vector<VirtualFoo> foos);
    virtual ~Foo();
    void doAllStuff();
protected:
    std::vector<VirtualFoo> foos;
};

And I would like to use it this way:

int main(int argc, char *argv[]){

    std::vector<ConcreteFoo> cfoos;
    cfoos.push_back(ConcreteFoo(1.0));
    cfoos.push_back(ConcreteFoo(2.0));

    Foo foo = Foo(cfoos);
    foo.doAllStuff();

}

Of course this does not work because cfoos is a vector of VirtualFoo and not ConcreteFoo.

Now, if I do not use a vector of VirtualFoo but a vector of VirtualFoo* and push back pointers to instances of ConcreteFoo, that seems to work fine.

Just, I am not sure it is the cleanest way to go. It's more like I did not think of any other way of doing this. Is doing this ok ?

Community
  • 1
  • 1
Vince
  • 3,979
  • 10
  • 41
  • 69
  • 5
    A vector of smart pointers is a clean solution, where the specific smart pointer depends on the ownership semantics you need. – juanchopanza Mar 18 '13 at 06:56
  • 1
    @juanchopanza Almost certainly shared for a vector? – Alex Chamberlain Mar 18 '13 at 07:06
  • @AlexChamberlain that isn't clear at all to me at the moment, but I haven't had a single cup of coffee yet. – juanchopanza Mar 18 '13 at 07:08
  • @AlexChamberlain I concur with that (and I'm slamming my coffee as I type this) =P – WhozCraig Mar 18 '13 at 07:34
  • 1
    @WhozCraig concur with what? Shared pointer? *Usually*, one wants the lifetime of the objects to be bound to that of the container holding them, so unique ownership would make more sense (the clients don't have to take ownership after all). – juanchopanza Mar 18 '13 at 07:44
  • @juanchopanza I'm almost always using shared_ptr in containers, only because I copy shared pointers out of the containers to local vars while working with them. I do, however see your point on unique ownership, no doubt. – WhozCraig Mar 18 '13 at 07:51
  • Alternatively you could template `Foo` to take any container of any type. – Peter Wood Mar 18 '13 at 07:54

1 Answers1

2

The vector with pointers of std::vector<VirtualFoo*> cfoos; is fine. You cannot instantiate abstract classes, hence the compiler fails to instantiate or specialize vector template that use abstract class as value. Pointing elements with base class pointers is fine which is Liskov substitution principle(http://en.wikipedia.org/wiki/Liskov_substitution_principle)

I agree with the comments from others that shared pointers is better solution so that you don't have to worry about memory management:

std::vector<shared_ptr<VirtualFoo>> cfoos;  
cfoos.push_back( shared_ptr<VirtualFoo> (new ConcreteFoo(1.0)) );   
cfoos.push_back( shared_ptr<VirtualFoo> (new ConcreteFoo(2.0)) );
Abhijit-K
  • 3,569
  • 1
  • 23
  • 31