vector of pure virtual base class

N

nw

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!
 
M

mlimber

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!

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
 
A

Alan Johnson

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.
 
N

nw

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!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top