473,407 Members | 2,315 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,407 software developers and data experts.

How to copy a vector if pointers to base class

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
Jun 27 '08 #1
10 2296
Alex Snast wrote:
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
Jun 27 '08 #2


Kai-Uwe Bux כתב:
Alex Snast wrote:
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
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'
Jun 27 '08 #3
In article
<84**********************************@25g2000hsx.g ooglegroups.com>,
Alex Snast <as****@gmail.comwrote:
Kai-Uwe Bux Ι·†
Alex Snast wrote:
æ
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

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();
}
}
Just for the record, Kai-Uwe was recommending something like this:

transform(rhs.repertory_.begin(), rhs.repertory_.end(),
back_inserter(repertory_), &deep_copy);

Or:

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

You can wrap the above to convert a bad_alloc into an OutOfMemory, but I
don't see a reason to bother...
Jun 27 '08 #4
Hi!

Daniel T. schrieb:
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
Jun 27 '08 #5
Frank Birbacher <bl************@gmx.netwrote:
Daniel T. schrieb:
Or:

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

The mem_fun will not do virtual dispatch here!
You are wrong. mem_fun was specifically designed to do virtual dispatch
in these cases...

struct Base
{
virtual Base* clone() = 0;
};

struct Derived1 : Base
{
virtual Base* clone() {
cout << "Derived1::clone() called\n";
return new Derived1;
}
};

int main()
{
vector<Base*old_vec;
vector<Base*new_vec;
old_vec.push_back( new Derived1 );
old_vec.push_back( new Derived1 );
old_vec.push_back( new Derived1 );
transform(old_vec.begin(), old_vec.end(),
back_inserter(new_vec), mem_fun(&Base::clone));
}
Jun 27 '08 #6
On Jun 9, 1:02 pm, Frank Birbacher <bloodymir.c...@gmx.netwrote:
Daniel T. schrieb:
Or:
transform(rhs.repertory_.begin(), rhs.repertory_.end(),
back_inserter(repertory_), mem_fun(&Base::clone));
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.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Jun 27 '08 #7
Hi!

James Kanze schrieb:
>The mem_fun will not do virtual dispatch here!

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
Jun 27 '08 #8
Frank Birbacher <bl************@gmx.netwrote:
James Kanze schrieb:
The mem_fun will not do virtual dispatch here!
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?
Have you checked out the output of your program above?

struct Base {
virtual void foo() { cout << "Base::foo()\n"; }
};

struct Dev : Base {
void foo() { cout << "Dev::foo()\n"; }
void test();
};

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

this->Base::foo();
(this->*&Base::foo)(); // fixed this line so it compiles
mem_fun(&Base::foo)(this);
bind(&Base::foo, this)();
}

int main()
{
Dev d;
d.test();
}

The output I get is:

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

IE: in every case except the first, Dev::foo() is called.
Jun 27 '08 #9
On Jun 9, 3:31 pm, Frank Birbacher <bloodymir.c...@gmx.netwrote:
James Kanze schrieb:
The mem_fun will not do virtual dispatch here!
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?
No extra help. It uses a pointer to member function.
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 ??
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.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Jun 27 '08 #10
Hi!

Daniel T. schrieb:
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
Jun 27 '08 #11

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

39
by: scooter | last post by:
Given this class heirarchy class Base{}; class A : public Base {}; class B : public Base {};
4
by: The Directive | last post by:
I can't understand why in this folling example the message "Base.Draw()" is printed. Shouldn't "Derive.Draw" be printed because of polymorphism? How can I rewrite this example using a vector to...
9
by: Gunnar G | last post by:
Is there anything like vector in STL, that performes deep copy of the elements it contains? I hope this will appear in future releases of STL :)
3
by: Nudge | last post by:
I am slightly confused, so please keep that in mind if I make only little sense. Assume I have a base class: class Base { ... }; and two derived classes: class Int : public Base { ......
5
by: Ernst Murnleitner | last post by:
Hello, is it possible to derive from std::vector and derive also its iterator? If I do it like in the example below, I get a problem when I need the begin of the vector: begin() returns the...
5
by: canned.net | last post by:
I have a class Scene that has several subclasses: World, Vault, etc. I fill a vector with these classes and then cannot go through and delete them. What's the trick to deleting pointers from a...
6
by: Jia | last post by:
Hi all, I have a class foo which has a static vector of pointers of type base class, and a static function to set this vector. #include <iostream> #include <vector> using namespace std;...
0
by: tech | last post by:
Hi, I have developed a little class to help implement dynamic menus in our application which has a UI. This allows our engine to send a MenuItem object to the UI which is an observer of the...
6
by: Peng Yu | last post by:
Hi, I'm wondering if the following assignment is lazy copy or not? Thanks, Peng std::vector<intv. v.push_back(1); v.push_back(2);
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.