Re: Copy constructor question.
On 27 Sep., 21:28, Vinesh S wrote:
i have for example
class A // abstract base class
{
...
};
class B : public A
{
...
};
class C : public A
{
...
};
also i have totally an unrelated class called D.
class D
{
D(A* basepointer , int k, int y) // constructor
{
....
basePtr = basePointer;
}
private:
A* basePtr;
};
QUESTION:
how do i write a copy constructor for Class D?
That depends on the behaviour you want in this situation. So far, you
did not say what the semantics of a D-object is and what kind of
relationship exists between D and A. Depending on what you want, you
might not even have to write a copy constructor at all.
There are at least three possible object<->object relationships:
(1) object x is part / is a real member (subobject) of object y
(2) object x is a logical part/member of object y but this is
implemented with a pointer for some reason (possible reasons:
polymorphism, optional member/nullable, variable number of
members (see vector), ...)
(3) object x is simply known by object y but neither physically
nor logically "part" of object y. Typically, this is
implemented with a pointer to x as member in y.
Only in the second case the compiler-generated copy operations would
do the wrong thing. So, in ths case you would have to define your own
copy operations to get the semantics you want (like calling a clone
function or something like this). There's maybe a fourth case: "1.5"
where ownership of x is shared among a couple of objects like y (via
shared_ptr, for example). Prefer (1) over (2) if possible. This saves
you the hassle of writing your own copy operations and your own
destructor.
1. problem i face is : if am not allowed to use memcpy ...
... i need to copy the value pointed by the basePtr in the copy
constructor to the resulting class.
Sounds like case (2). I suggest adding a clone function to A:
class A { // abstract base class
public:
virtual A~() {}
virtual A* clone() const = 0;
...
};
This way you can simply invoke a clone function in D's copy-ctor:
D::D(D const& x)
: baseptr(x.baseptr->clone())
{}
In case baseptr==nullptr is part of the D class' invariant, you should
add a null pointer test in there:
D::D(D const& x)
: baseptr(x.baseptr ? x.baseptr->clone() : 0)
{}
If you need this pattern a lot, it might be a good idea to generalize
this and to write your own cloning smart pointer, so that the
definition of D reduces to
class D {
public:
explicit D(A* ptr) : ptr(ptr_) {}
private:
clone_ptr<A> ptr_;
};
What is nice about this approach is:
- The responsibility of managing the A-object is moved to ptr_
- This frees you from having to define copy operations and a
destructor for D
I'd even say that this corresponds to important "modern C++ design
principles":
- Make a class "manage" at most one resource
("manage" in the sense of providing custom copy ops and a dtor)
- Avoid having to write custom copy operations and dtors for many
of your classes.
In addition, I suggest to exploit covariant return types w.r.t. the
virtual clone member function.
Cheers!
SG