By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
448,617 Members | 1,605 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 448,617 IT Pros & Developers. It's quick & easy.

vector of pure virtual base class

P: n/a
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 _precclass Base {
public:
_prec i;

Base() {
i = 12;
}

virtual void f() = 0;

};

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

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

Collect() {
}

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

int main() {
Derived<intd;
Collect<intc;

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!

Jan 25 '07 #1
Share this Question
Share on Google+
3 Replies


P: n/a
On Jan 25, 2:39 pm, "nw" <n...@soton.ac.ukwrote:
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 _precclass Base {
public:
_prec i;

Base() {
i = 12;
}

virtual void f() = 0;

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

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

Collect() {
}

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

};int main() {
Derived<intd;
Collect<intc;

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

Jan 25 '07 #2

P: n/a


On Jan 25, 11:39 am, "nw" <n...@soton.ac.ukwrote:
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

Jan 25 '07 #3

P: n/a
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!

Jan 26 '07 #4

This discussion thread is closed

Replies have been disabled for this discussion.