How to copy a vector if pointers to base class

A

Alex Snast

hello

I'm trying to implement a copy constructor for a vector of pointers to
a base class (which is abstract)

My question is how would i know what kind of new type should i
allocate since the base poiner can have multipull meanings.

i know i can use dynamic_cast however i really don't like this
solution and i was wondering is i can do something better

thanks
 
K

Kai-Uwe Bux

Alex said:
hello

I'm trying to implement a copy constructor for a vector of pointers to
a base class (which is abstract)

My question is how would i know what kind of new type should i
allocate since the base poiner can have multipull meanings.

i know i can use dynamic_cast however i really don't like this
solution and i was wondering is i can do something better

The standard trick is to provide a virtual clone() member in the base class.
You can then copy the vector by using std::transform with a back_inserter
and a functor like this

Base* deep_copy ( Base * ptr ) {
return( ptr->clone() );
}

or some of these unreadable pointer to member function binders.

You can also google the archives for copy_ptr or clone_ptr to find smart
pointers with deep copy semantics. Those are non-standard and might make
your code harder to maintain for others since they might not be familiar
with those libraries. On the plus side, you don't need to do anything to
copy a vector of those since the copy constructor of the smart pointer will
to the job.


Best

Kai-Uwe Bux
 
A

Alex Snast

Kai-Uwe Bux כתב:
The standard trick is to provide a virtual clone() member in the base class.
You can then copy the vector by using std::transform with a back_inserter
and a functor like this

Base* deep_copy ( Base * ptr ) {
return( ptr->clone() );
}

or some of these unreadable pointer to member function binders.

You can also google the archives for copy_ptr or clone_ptr to find smart
pointers with deep copy semantics. Those are non-standard and might make
your code harder to maintain for others since they might not be familiar
with those libraries. On the plus side, you don't need to do anything to
copy a vector of those since the copy constructor of the smart pointer will
to the job.


Best

Kai-Uwe Bux

Thanks for the help. Worked just find even though i haven't used
std::transform but rather wrote my own method
Storerepository::Storerepository(const Storerepository& rhs)
throw(OutOfMemory)
{
try {
for (const_repertory_iterator cit = rhs.repertory_.begin(); cit !=
rhs.repertory_.end(); ++cit) {
this->repertory_.push_back((*cit)->clone());
}
}
catch(std::bad_alloc){
throw OutOfMemory();
}
}

thanks again'
 
F

Frank Birbacher

Hi!
Or:

transform(rhs.repertory_.begin(), rhs.repertory_.end(),
back_inserter(repertory_), mem_fun(&Base::clone));

The mem_fun will not do virtual dispatch here! But you can always do it
like the "C++ Conding Standards" say: have a public non-virtual function
which calls the virtual protected function. Then the above would work.

class Base {
public:
Base* clone() const { return doClone(); }
protected:
virtual Base* doClone()=0;
};

Frank
 
J

James Kanze

Daniel T. schrieb:
The mem_fun will not do virtual dispatch here!

The mem_fun has exactly the same semantics of calling the
function directly; if the function is declared virtual in Base,
and you call it correctly with a pointer to the base, then it
will use virtual dispatch.
 
F

Frank Birbacher

Hi!

James said:
The mem_fun has exactly the same semantics of calling the
function directly;

This is nothing a boost::bind could do, right? The mem_fun has extra
help from the compiler here, right?
if the function is declared virtual in Base,
and you call it correctly with a pointer to the base, then it
will use virtual dispatch.

So, the following won't do the same?

struct Base {
virtual void foo() {}
};

struct Dev : Base {
void foo() {}
void test();
};

void Dev::test() {
using boost::bind;

this->Base::foo(); //calls Base::foo
this->*(&Base::foo)(); //calls Base::foo ??
mem_fun(&Base::foo)(this); //calls Dev::foo ?? WTF?
bind(&Base::foo, this)(); //calls Base::foo ??
}

I don't get it. How does mem_fun work?

Frank
 
J

James Kanze

James Kanze schrieb:
This is nothing a boost::bind could do, right? The mem_fun has
extra help from the compiler here, right?

No extra help. It uses a pointer to member function.
So, the following won't do the same?
struct Base {
virtual void foo() {}
};
struct Dev : Base {
void foo() {}
void test();
};
void Dev::test() {
using boost::bind;
this->Base::foo(); //calls Base::foo
this->*(&Base::foo)(); //calls Base::foo ??

Doesn't compile.
(this->*(&Base::foo))() ;
calls Dev::foo.
mem_fun(&Base::foo)(this); //calls Dev::foo ?? WTF?

Calls Dev::foo.
bind(&Base::foo, this)(); //calls Base::foo ??

Calls Dev::foo.
I don't get it. How does mem_fun work?

It uses a pointer to member function.
 
F

Frank Birbacher

Hi!
The output I get is:

Base::foo()
Dev::foo()
Dev::foo()
Dev::foo()

IE: in every case except the first, Dev::foo() is called.

o_O I'm sorry, I have a complete misunderstanding of this issue.

Thanks to both of you, Daniel and James, for clearing things up.

Frank
 

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,756
Messages
2,569,540
Members
45,024
Latest member
ARDU_PROgrammER

Latest Threads

Top