Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

vector of pure virtual base class

156 views
Skip to first unread message

nw

unread,
Jan 25, 2007, 2:39:41 PM1/25/07
to
Hi,

I have three classes, a template pure virtual base class, a template
derived class and a third which I would like to use to store copies of
the derived class. The code looks like this:

#include <iostream>
#include <vector>

using namespace std;

template <class _prec> class Base {
public:
_prec i;

Base() {
i = 12;
}

virtual void f() = 0;

};

template <class _prec> class Derived : public Base<_prec> {
public:
void f() {
std::cout << this->i << std::endl;
}
};

template <class _prec> class Collect {
public:
vector <Base<_prec> > vec;

Collect() {
}

void g(Base<_prec> &in) {
vec.push_back(in);
}
};

int main() {
Derived<int> d;
Collect<int> c;

c.g(d);

return 0;
}

This results in linking errors, which result from vector being unable
to create a copy of the pure virtual class. Can anyone suggest how I
should solve this?

My first attempted was to make the function in Base virtual, rather
than pure virtual (i.e. virtual void f() {}). This then compiles,
however when the object is extracted from the vector (i.e. I do
vec[0].f() in Collect), the base method is called not that of the
derived class. Any ideas?

I think this should all be standard C++ but I'm using gcc version 4.1.2
to compile this code.

Any help appreciated!

mlimber

unread,
Jan 25, 2007, 2:50:03 PM1/25/07
to

To operate on an object polymorphically, you need to either use a
pointer or a reference to access it. std::vectors on the other hand,
hold a copy of whatever object you put in them, so your vector either
needs to be of Base*, or probably better, std::tr1::shared_ptr<Base>
(aka boost::shared_ptr<Base>).

BTW, I'd guess you're getting compiler errors, not linker errors.

Cheers! --M

Alan Johnson

unread,
Jan 25, 2007, 2:56:45 PM1/25/07
to

On Jan 25, 11:39 am, "nw" <n...@soton.ac.uk> wrote:
> Hi,
>
> I have three classes, a template pure virtual base class, a template
> derived class and a third which I would like to use to store copies of
> the derived class. The code looks like this:

> This results in linking errors, which result from vector being unable


> to create a copy of the pure virtual class. Can anyone suggest how I
> should solve this?

Templates are just obfuscating the core problem, which is that you are
trying to instantiate an abstract class, which just can't be done.
When you try to add to a vector of your abstract base type, you are
essentially doing the following:

class abstract_base
{
public:
virtual int f() = 0 ;
} ;

class concrete : public abstract_base
{
virtual int f() { return 42 ; }
} ;

int main()
{
concrete c ;
abstract_base ab(c) ; // Error, can't create an instance
// of an abstract class.
}


Even if your base class was not abstract, virtual methods only get
dynamically dispatched when called via pointers or references, so
storing a vector of your base class still wouldn't achieve what you
want.

The solution? Store a vector of pointers to your base class. Example:
std::vector<abstract_base *> v ;
concrete c ;
v.push_back(&c) ;

If you want the vector to "own" the objects to which it points, then
your easiest route will probably be to create the objects dynamically,
and keep a vector of boost::shared_ptr.

--
Alan Johnson

nw

unread,
Jan 26, 2007, 6:44:04 AM1/26/07
to
> The solution? Store a vector of pointers to your base class. Example:
> std::vector<abstract_base *> v ;
> concrete c ;
> v.push_back(&c) ;
>
> If you want the vector to "own" the objects to which it points, then
> your easiest route will probably be to create the objects dynamically,
> and keep a vector of boost::shared_ptr.

Many thanks for your and mlimber's advice, I'll give it a go!

Thanks again!

0 new messages