> | No, the parent class does not have a copy constructor -- or even an
| assignment operator. :-( But thanks for the suggestion.
Sorry to be picky here, but you have to be specific.
If the parent class doesn't have (*declare*) a copy-constructor or
assignment operator, a default compiler-generated implementation
of these functions will exist and be accessible.
(Let's call this the "copy constructor method" -- for the discussion below.)
Durn, I forgot! *blush* Yes, the parent class doesn't declare a copy
constructor, so it has the default. The default copy constructor copies
ptr values, but that's okay because we can write a little method to
allocate new memory (assigning new ptr values to our new object).
Thanks! :-)
I would stay away from memcpy. It does lead to real problems
(not only in theory, though it depends on the contents of Parent).
eg, I found that if some of the data members in Parent are NULL, then
memcpy() results in a NULL ref exception (even *if* I try to allocate
new memory to the child data members). Strange.
If you really need a hack, the following might be more
reliable:
// File: Derived.cpp
#define private public //illegal, but typically works in practice...
#include "Parent.h"
#undef private
//... other includes ...
// and use the copy-constructor of Parent,
// as suggested in my previous reply
(Let's call this the "macro hack method" -- for the discussion below.)
Ah, yes, defining keywords as macros. (I just saw that done for "new"
somewhere.) ;-) Dangerous if someone tries to use class Derived in with
*precompiled* Parent code, I'd think (because then the "private" macro
wouldn't have been defined when Parent was compiled).
-------//-------
FYI, below is my complete test program, hacks and all. Only the copy
constructor method (and the macro hack method) is 100% reliable. I have
no questions. :-)
--Suzanne
#include <iostream>
#define COUT std::cout
#define FLUSH std::flush
#define private public //----- BEGIN HACK -----
class Parent
{
private:
int* mX;
protected:
int* mY;
public:
int* mZ;
public:
Parent(int* x=NULL, int* y=NULL, int* z=NULL) : mX(x), mY(y), mZ(z)
{
if (mX==NULL) mX = new int(3);
if (mY==NULL) mY = new int(5);
if (mZ==NULL) mZ = new int(7);
}
virtual ~Parent() { delete mX; delete mY; delete mZ; }
void print() { COUT << "(" << mX << ", " << mY << ", " << mZ << ")\n"
<< "(" << *mX << ", " << *mY << ", " << *mZ <<
")\n----------------\n" << FLUSH; }
};
#undef private //----- END HACK -----
class Derived : public Parent
{
public:
Derived() {}
//************************************************** ***********************
// WORKS
//************************************************** ***********************
Derived(Parent& rhs) : Parent(rhs) { fixupPtrs(); }
//************************************************** ***********************
Derived& copy1(Parent& p) // WARNING: Works here iff ptrs are
non-NULL -- but undefined in general
{
memcpy(this, static_cast<Derived*>(&p), sizeof(Derived));
fixupPtrs();
return *this;
}
Derived& copy2(Parent& p) // WARNING: Works here iff ptrs are
non-NULL -- but undefined in general
{
memcpy(static_cast<Parent*>(this), &p, sizeof(Parent));
fixupPtrs();
return *this;
}
Derived& copy3(Parent& p) // WARNING: Works here iff "private" is
macro #define'd as "protected" or "public"
{
Derived& d = static_cast<Derived&>(p);
mX = d.mX!=NULL ? new int(*(d.mX)) : new int(3);
mY = d.mY!=NULL ? new int(*(d.mY)) : new int(5);
mZ = d.mZ!=NULL ? new int(*(d.mZ)) : new int(7);
return *this;
}
Derived& copy4(Parent& p) // WARNING: Senseless crap -- and
sometimes gives NULL ref exception!!
{
const_cast<Derived*>(this) = &(Derived(p));
fixupPtrs();
return *this;
}
private: // Give this object different ptrs from (but the same values
as) the parent from which it was copied
void fixupPtrs() { mX = new int(*mX); mY = new int(*mY); mZ = new
int(*mZ); }
};
int main(int argc, char** argv)
{
Parent* p = new Parent();
Derived* d = new Derived();
COUT << "//////////////////////// Parent: ///////////////////////\n";
p->print();
// ----- All of these are *unsafe* -----
COUT << "//////////////////////// Derived: ///////////////////////\n";
d->copy1(*p).print();
d->copy2(*p).print();
d->copy3(*p).print();
//d->copy4(*p).print(); // Yeeks, gives NULL ref exception
// ----- This is *safe* -----
COUT << "//////////////////////// Derived: ///////////////////////\n";
Derived* d2 = new Derived(*p);
d2->print();
delete p;
delete d;
delete d2;
}