Let's say I have a class A and B where B derives from A. And later I have a pointer A* which can point to an object class A or object class B. Now I'd like to copy this object under pointer without knowledge which object is pointed to by this pointer so if there is an A object then I'd like to copy an A object but if it's B then I'd like to copy B. I'd like to omit RTTI and dynamic casting. Do you have an idea how to do it? Or must I implement something like virtual cloning function and call it explicitly?
-
What have you tried... And what is going wrong? We work with code, we don't generate it.eatonphil– eatonphil2013-08-21 17:02:26 +00:00Commented Aug 21, 2013 at 17:02
-
5" Or i must implement something like virtual cloning function and call it explicit?" Yes, that. (You can search for "clone" and "virtual copy constructor".)gx_– gx_2013-08-21 17:03:48 +00:00Commented Aug 21, 2013 at 17:03
Add a comment
|
2 Answers
The cloning virtual function is the most typical approach for this, for example as
class Base {
public: virtual Base* clone() { return new Base(*this); }
};
class Derived : public Base {
public: virtual Base* clone() { return new Derived(*this); }
};
Sometimes however, when you have a pointer to Derived and you clone it, you suddenly have a pointer to Base while you know that it is derived. A down-cast is then needed, if you want to access Derived-specific members.
According to C++98-standard you can actually change the return type to the derived type, e.g.
class Base {
public: virtual Base* clone() { return new Base(*this); }
};
class Derived : Base {
public: virtual Derived* clone() { return new Derived(*this); } //will overload Base::clone
};
3 Comments
gx_
Not only "some" compilers, every Standard-compliant compiler. It's called "covariant return type" and has been incorporated in the C++98 Standard a long time ago. By the way you're missing a public, it should be
class Derived : public Base (otherwise "the outside" can't convert a Derived* to Base*)Michal W
Oh, that information about covariant return type can be very useful, thanks!
CygnusX1
@gx_ fixed as per your comment
In the simple case of memberwise copy it seems strightforward:
#include<iostream>
using namespace std;
class A{
public:
~A(){}
A() : _x('A') {}
void foo() { cout << _x << endl; }
protected:
char _x;
};
class B : public A{
public:
~B(){}
B() { _x = 'B';}
};
int main()
{
A* a = new A();
A* b = new B();
A* c(a);
c->foo(); //A
A* d(b);
d->foo(); //B
delete a,b;
}
3 Comments
gx_
You're just copying pointers. The OP wanted to copy objects through pointers (and has already been answered). Besides,
delete a,b; is horribly wrong, it's basically like delete a; then b; alone (statement with no effect), so you delete the A but not the B (warning: right operand of comma operator has no effect + live example). And even if you fix that, you'll be deleting a B through a pointer-to-A and A's destructor is not virtual, so it will call the wrong destructor. ("The amazing C++ genius", says your signature... you have a sense of humor.)cpp
@gx_: Thanx, you have thought me alot.
cpp
My answer is wrong but I will not delete it as I found gx_ comment useful