const 'correctness' question

B

Bit Byter

I have a 'root' object that serves as a container/parent for several
other objects like so:

class myRoot {
public:
myRoot();
virtual ~myRoot();
void* operator new(size_t);
operator delete(void*);

setChildX(X*);
setChildY(Y*);
setChildZ(Z*);

private:
myRoot(const myRoot&);
myRoot operator= (const myRoot&);

X* m_x ;
Y* m_y ;
Z* m_z ;
};


with the setChild... methods, is it better to write them as ff (using
setChildX as an example):

setChildX(X*); OR
setChildX(const X*); OR even
setChildX(const X&);

with the variable declarations (using variable of type X* as an
example),

should I declare the variable to be :

X* m_x OR
const X* m_x

The intended lifecycle for the child objects is as ff:

1). They are created and initialized OUTSIDE the parent
2). Once they are assigned to the parent object, they can no longer be
changed (i.e. const)
3). The parent destroys all its children upon parent's death (i.e. in
parent's destructor)

Given the intended life cycle, what is the best way of declaring the
methods and the variables that will hold the ptrs to the child objects?
 
N

Noah Roberts

Bit said:
I have a 'root' object that serves as a container/parent for several
other objects like so:

class myRoot {
public:
myRoot();
virtual ~myRoot();
void* operator new(size_t);
operator delete(void*);

setChildX(X*);
setChildY(Y*);
setChildZ(Z*);

private:
myRoot(const myRoot&);
myRoot operator= (const myRoot&);

X* m_x ;
Y* m_y ;
Z* m_z ;
};


with the setChild... methods, is it better to write them as ff (using
setChildX as an example):

setChildX(X*); OR
setChildX(const X*); OR even
setChildX(const X&);

with the variable declarations (using variable of type X* as an
example),

should I declare the variable to be :

X* m_x OR
const X* m_x

The intended lifecycle for the child objects is as ff:

1). They are created and initialized OUTSIDE the parent

Bad choice unless absolutely necessary.
2). Once they are assigned to the parent object, they can no longer be
changed (i.e. const)

Can only be enforced within the parent object. Anyone else can still
change the object.
3). The parent destroys all its children upon parent's death (i.e. in
parent's destructor)

The parent should clone the children and keep its own copies.
Given the intended life cycle, what is the best way of declaring the
methods and the variables that will hold the ptrs to the child objects?

You can declare the pointer variables as const both within the object
and the parameter. You can still delete a const pointer. Again though
you cannot enforce the 'no-change' requirement except in the parent
object. Any client can change the object if they desire...especially
the one that created the 'child' to begin with. IE:

X * x = new X;

root.setChild(x); // even assuming setChild has const X* as parameter
type, my X is still non-const

x.changeInternals(); // perfectly valid. root now has a changed X.
 
V

Victor Bazarov

Bit said:
I have a 'root' object that serves as a container/parent for several
other objects like so:

class myRoot {
public:
myRoot();
virtual ~myRoot();
void* operator new(size_t);
operator delete(void*);

setChildX(X*);
setChildY(Y*);
setChildZ(Z*);

private:
myRoot(const myRoot&);
myRoot operator= (const myRoot&);

X* m_x ;
Y* m_y ;
Z* m_z ;
};


with the setChild... methods, is it better to write them as ff (using
setChildX as an example):

setChildX(X*); OR
setChildX(const X*); OR even
setChildX(const X&);

with the variable declarations (using variable of type X* as an
example),

should I declare the variable to be :

X* m_x OR
const X* m_x

The intended lifecycle for the child objects is as ff:

1). They are created and initialized OUTSIDE the parent

What would be the life of an instance of "myRoot" without those child
objects? Wouldn't it make sense to only create a 'myRoot' once all
the child objects are ready? If so, then perhaps the constructor of
'myRoot' should take those pointers are arguments.
2). Once they are assigned to the parent object, they can no longer
be changed (i.e. const)

Again, perhaps they shouldn't be "assigned", but instead given to the
"parent object" during its construction?
3). The parent destroys all its children upon parent's death (i.e. in
parent's destructor)

Given the intended life cycle, what is the best way of declaring the
methods and the variables that will hold the ptrs to the child
objects?

The more const, the merrier. I would even consider

class myRoot {
...
myRoot(const X* px, const Y* py, const Z* pz) :
m_x(px), m_y(py), m_z(pz) { ...

const X* const m_x;
const Y* const m_y;
const Z* const m_z;
};

and do away with 'setChildXYZ' altogether.

V
 
D

dan2online

class myRoot {
...
myRoot(const X* px, const Y* py, const Z* pz) :
m_x(px), m_y(py), m_z(pz) { ...

const X* const m_x;
const Y* const m_y;
const Z* const m_z;
};

and do away with 'setChildXYZ' altogether.

The class also needs a default constructor to initaialize my_x, m_y,
m_z to NULL.
It is flexible to use setChildX, setChildY, and setChildZ for
lazy-binding repectively.
 
M

mlimber

dan2online said:
The class also needs a default constructor to initaialize my_x, m_y,
m_z to NULL.
It is flexible to use setChildX, setChildY, and setChildZ for
lazy-binding repectively.

That's a requirement for the OP to decide, but it is not necessary. As
Victor said, the more const the merrier (i.e., the easier the code is
to write, understand, and maintain), and I would certainly prefer his
version if possible.

Cheers! --M
 
M

mlimber

Bit said:
I have a 'root' object that serves as a container/parent for several
other objects like so:

class myRoot {
public:
myRoot();
virtual ~myRoot();
void* operator new(size_t);
operator delete(void*);

setChildX(X*);
setChildY(Y*);
setChildZ(Z*);

private:
myRoot(const myRoot&);
myRoot operator= (const myRoot&);

X* m_x ;
Y* m_y ;
Z* m_z ;
};


with the setChild... methods, is it better to write them as ff (using
setChildX as an example):

setChildX(X*); OR
setChildX(const X*); OR even
setChildX(const X&);

with the variable declarations (using variable of type X* as an
example),

should I declare the variable to be :

X* m_x OR
const X* m_x

The intended lifecycle for the child objects is as ff:

1). They are created and initialized OUTSIDE the parent
2). Once they are assigned to the parent object, they can no longer be
changed (i.e. const)
3). The parent destroys all its children upon parent's death (i.e. in
parent's destructor)

Given the intended life cycle, what is the best way of declaring the
methods and the variables that will hold the ptrs to the child objects?

See the other posts for answers to this question, but let me also
recommend that you use std::auto_ptr to pass objects into the owner
class in order to clearly indicate that myRoot takes over
responsibility for them. Likewise, I would recommend using a smart
pointer to hold the members for exception safety and easy of use.
std::auto_ptr would work, but std::tr1::scoped_ptr (or
boost::scoped_ptr) would be better.

Cheers! --M
 

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

No members online now.

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,045
Latest member
DRCM

Latest Threads

Top