Solved

C++ Programming Style - Using MyClass c = new MyClass(stuff) instead of MyClass c(stuff); Are Java style new MyClass() better than regular objects for C++ Dev?

Posted on 2004-04-19
23
364 Views
Last Modified: 2010-04-01
Hi,

I've been recently creating a C++ based project of which I've been using Java style

//in class declaration
class Foo{
Foo();
MyClass * c;
MyBClass *b;
}


//in constructor
Foo::Foo(){
c = new MyClass();
b = new MyBClass();
}

style declarations. My question is, is this the regular way to create objects for class objects, or should I not use the "new" style (Java-like) method of instantiating classes within classes.

The biggest issue that comes up is that I want to be able to make *copies* of the values that these pointers point to, to be able to pass to other classes.

Lets say, I would do something like this:

Foo * myfoo = new Foo();

Foo * myfoo2 = myfoo; //which doesn't work, because I want to be able to modify myfoo2 without modifying myfoo :(.

Is this a pointer copy constructor issue? If so, how should I go about it? Is there some easy way to copy all values from within a class pointer into another class pointer?

Very much thanks in advance!

-Edward
0
Comment
Question by:edwardt
  • 9
  • 9
  • 4
  • +1
23 Comments
 
LVL 86

Accepted Solution

by:
jkr earned 500 total points
ID: 10862576
>> My question is, is this the regular way to create objects for class objects,
>>or should I not use the "new" style (Java-like) method of instantiating classes within classes

Both 'yes' and 'no'. You can of course use this technique, but have to make sure to 'delete' the pointers to the instances in your destructor. Depending on whether you *need* to use dynamic allocation, you alternatively could use

//in class declaration
class Foo{
Foo();
MyClass c;
MyBClass b;
}


//in constructor
Foo::Foo(){
}

>>The biggest issue that comes up is that I want to be able to make *copies* of the values
>>Lets say, I would do something like this:
>>Foo * myfoo = new Foo();
>>Foo * myfoo2 = myfoo; //which doesn't work, because I want to be able to modify myfoo2 without modifying
>>myfoo :(.
>>Is this a pointer copy constructor issue? If so, how should I go about it?

Again 'yes' and 'no'. If you want to make a copy of an object and do not want to touch the original, you could use


Foo * myfoo = new Foo();
Foo * myfoo2 = new Foo();

*myfoo2 = *myfoo; // assing the objects by value

which will work unless your classes become more complex. Thus, providing a copy constructor and an assignment operator before problems arise is good design, e.g.

//in class declaration
class Foo{
public:
Foo();
Foo(const Foo&r); // copy constructor
Foo& operator=(const Foo&r); // assgnment operator

protected:
MyClass  c;
MyBClass b;

 Foo& copy ( const Foo& r);
}

Foo::Foo(const Foo&r) // copy constructor
{
  copy ( r);
}
Foo& Foo::operator=(const Foo&r) // assgnment operator
{
   return copy ( r);
}
Foo& Foo::copy(const Foo&r)
{

    // assign each element to is corresponding value in our object

    a = r.a;
    b = r.b;

    return *this;
}

0
 

Author Comment

by:edwardt
ID: 10863334
Hi JKR,

For the most part, many of my items in my classes are pointers, like

class Foo{
Address *a;
AnotherClass b*;
RegularClass c;
char * d;
}

What additional benefit does making a copy constructor do beyond something like the  *myfoo2 = *myfoo; you have?

In light of

Foo& Foo::copy(const Foo&r)
{

    // assign each element to is corresponding value in our object

    a = r.a;
    b = r.b;

    return *this;
}

Do you mean I should put something like:

Foo& Foo::copy(const Foo&r)
{

    // assign each element to is corresponding value in our object

    a(r.a); //    a = r.a;
    b(r.b); //    b = r.b;
    c = r.c;
    d = r.d

    return *this;
}

And then make copy constructors for classes a and b as well?

Thank you again - this is a big help.

-Edward
0
 
LVL 86

Expert Comment

by:jkr
ID: 10863426
>>What additional benefit does making a copy constructor dobeyond something
>> like the  *myfoo2 = *myfoo; you have?

*myfoo2 = *myfoo will invoke the copy constructor if one is present, making sure that each member will be copyied to the corresponding one in the target object.

>>Do you mean I should put something like:
>> [...]
>>And then make copy constructors for classes a and b as well?

Again, it is a good practise to provide copy constructors for non-trivial classes. It seems a little overhead at first, but the benefit is less error prone code...
0
 
LVL 30

Expert Comment

by:Axter
ID: 10863628
>>My question is, is this the regular way to create objects for class objects, or should I not use the "new" style (Java-like)
>>method of instantiating classes within classes.

I recommend not using pointers if you don't need it.
If you're not getting any benifit in using the pointer, then you're better off using (static) non-pointers variables.

There's a greater risk for bugs when using pointers.
So your code is safer if you don't use them.
0
 

Author Comment

by:edwardt
ID: 10863676
0
 
LVL 30

Expert Comment

by:Axter
ID: 10863720
There are two main reasons for using pointers.
1.      Need to determine a virtual class descendant type at runtime
2.      Need to reference an object that does not have complete definition.

If neither applies to your object, then you shouldn’t use pointers.

There are other reasons like "circular reference", "class implementation hiding", etc....
However these other reasons fall in the above two categories.
0
 

Author Comment

by:edwardt
ID: 10863937
Ack! - Then that means I might need to go back to my (large) set of files and replace all class pointer members to regular members.

Then again, if I leave stuff as pointers, I would probably have to start adding a lot of stuff into the destructor functions :(.

I'm pretty sure there are areas where I *don't* want to have an addressed copy of a pointer. However, there are areas that I would want pointers... lemme see - (from http://www.harpercollege.edu/bus-ss/cis/166/mmckenzi/lect10/l10a.htm

Why use pointers?
Connect data structures in memory (lists, chains, queues, trees, graphs)
Allows a function to modify its arguments
Access dynamic memory (only way is via pointers)
Concise and efficient array access
Efficiently pass structure to a function

From these, I do need to pass these "classes" to functions regularly (very regularly!) and allow functions to modify their arguments.

So at the very least, I do need
1) To be able to make deep copies of classes pointers point to
2) to be able to modify arguments of classes I pass into functions.

Beyond that, I don't think there is much other requirements that I have to make me need to decide to use pointers instead of regular members. What do you think?

-Edward
0
 

Author Comment

by:edwardt
ID: 10863964
Ah - your second reason, Axter - 2.     Need to reference an object that does not have complete definition.

I think I need that because in some areas, I reference an object

BaseClass * b = somefunction->returnstuff();

where there are pure virtual functions of b, whose child classes implement the real function... If I did
BaseClass b = somefuction.... then it would give me an error, in that b hasn't implemented particular functions ;P (although I guess I could just implement those functions with a "blank" function in the .cpp file).

-Edward
0
 

Author Comment

by:edwardt
ID: 10864731
When I began thinking of these copy constructors, I realized that I also need to deal with the fact that my current class might have base class members that need to be copied. Is there a quick way to copy base class members too?

Also, I realized that sometimes I might need to figure out which child class I might need to deal with, like

MyBaseClass
MyClass
MyChildClass1
MyChildClass2

whereas, I might need to do a copy of

MyClass *c = getmyrealClass();//returns either a pointer to childclass1 or childclass2
MyClass *d = new MyClass(c); //whereas now, I have to

it could be something like
if(c is of childclass1){
d = new MyChildClass1(c);
} else {
d = new MyChildClass2(c);
}

right? :)

Thanks!


-Edward
0
 
LVL 30

Expert Comment

by:Axter
ID: 10865762
>>Why use pointers?

I'm sorry, but that link is giving you some bad advise.
Those are not valid reason to use pointers, and certainly not valid reason to have a member variable as a pointer.

First point:
>>Connect data structures in memory (lists, chains, queues, trees, graphs)
Since you can use STL code for this, you don't need to use a member poitner.
Example
class foo
{
 public:
 std::vector<int> A_dynamic_array_of_int;
 std::list<int> A_list_of_int;

By using STL library, you can let it create the pointers, and it will also do the clean up automatically.

0
 
LVL 30

Expert Comment

by:Axter
ID: 10865781
Second point:
>>Allows a function to modify its arguments

This is not a good reason at all.
Your variable does not need to be a pointer in order to have a function modify it.

Example:

void somefunction1(int &var)
{
 ++var;
}

void somefunction2(int *var)
{
 ++(*var);
}


int main()
{
  int MyVarThatIsNotAPointer = 0;
  somefunction1(MyVarThatIsNotAPointer ); //Pass via reference
  cout << MyVarThatIsNotAPointer << endl;
  somefunction2(&MyVarThatIsNotAPointer ); //Pass via pointer
  cout << MyVarThatIsNotAPointer << endl;

As you can see, MyVarThatIsNotAPointer is not a pointer, but it can be pass to a function that takes a reference, and it can be pass to a function that takes a pointer.
Both functions are able to modify the calling object's variable.
0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 30

Expert Comment

by:Axter
ID: 10865786
>>Access dynamic memory (only way is via pointers)

You can access and create dynamic memory via any of the STL containers.
std::vector
std::list
std::deque
std::map
etc...
All the above containers will create dynamic memory, and will handle the pointers for you, with regards to creating and deleting.
No need for you to have a pointer member variable for this reason.
0
 
LVL 30

Expert Comment

by:Axter
ID: 10865791
>>Concise and efficient array access

The STL containers can give you concise and efficient access to an array.
This is another bad reason for having a pointer.
0
 
LVL 30

Expert Comment

by:Axter
ID: 10865803
>>Efficiently pass structure to a function

More BS.
You variable does not need to be a poitner to pass a structure to a function.

Example:

void somefunction1(foofoo &var)
{
 //Do something to foofo
}

void somefunction2(foofoo *var)
{
 //Do something to foofo
}


int main()
{
  foofoo MyVarThatIsNotAPointer = 0;
  somefunction1(MyVarThatIsNotAPointer ); //Pass via reference
  somefunction2(&MyVarThatIsNotAPointer ); //Pass via pointer

As you can see, the above foofoo variable is not a pointer, yet you can pass it to a function that takes a pointer.
Moreover, you can efficiently, and more safely pass it to a function that takes a reference instead, in which case a pointer is not required at all.

References are just as efficient as poitners, and they're safer, easier to code, and easier to read.
0
 
LVL 30

Expert Comment

by:Axter
ID: 10865822
edwardt,
If you look at the top of the link you posted, you would have notice the following:
Introduction to Programming in C

C has different rules then C++.
Moreover, there are some old C compilers in which SOME of those reasons would actually be valid.
For example, the Old Microsoft C compiler did not take reference arguments, you had to pass via pointers.
However, that still didn't mean you had to create the object using a pointer.
0
 
LVL 30

Expert Comment

by:Axter
ID: 10865836
>>I think I need that because in some areas, I reference an object
>>BaseClass * b = somefunction->returnstuff();

Yes, that is a good reason for having a pointer.

>>When I began thinking of these copy constructors, I realized that I also need to deal with the fact that my current class might have base class members >>that need to be copied. Is there a quick way to copy base class members too?

You should create a copy constructor for the base class, so that it does the job of copying it's members.  This is not a job you want the decedant class to do.

Just remember, that when ever you use a pointer member variable, you add a lot more work for yourself.
For the class to be safe, you need to add a copy constructor, a assignment operator, and a destructor.
None of these are required if you use a non-pointer variable instead.
0
 

Author Comment

by:edwardt
ID: 10871689
In the case where I work with base classes

BClass *b1 = function->returnChildClass();
BClass *b2 = new BClass(b1);

lets assume that returnChildClass() returns some child class of BClass. ChildClass has its own members.

When I do b2 = new BClass(b1);, how do I make sure the member values of the child class (which is masqueraded as  BClass) make it into b2?

Thanks.

-Edward
0
 

Author Comment

by:edwardt
ID: 10873240
Another issue I come up with are that some members of my class have virtual functions, like

MyClass {

//members
AClass *a

BClass *b

}

where ACLass and BClass have virtual functions undefined... so when I do

MyClass & MyClass ::copy(const MyClass&r)
{
a = new AClass(*r.a)

return *this;
}

the compiler gives me errors, saying certain functions of AClass are virtual and not defined... the only way to fix this (it seems) is to go a level higher and instantiate the Child class, like
a = new ATheRightChildClass(*r.a);

But I'm not sure how to do that :P

-Edward
0
 
LVL 86

Expert Comment

by:jkr
ID: 10881813
>>where ACLass and BClass have virtual functions undefined

You mean 'pure virtual' or just 'virtual'?
0
 

Author Comment

by:edwardt
ID: 10883323
Pure virtual... I guess I "could" make them virtual just to get past this issue... but then I still have the issue of copying members of child classes....

Thanks.

-Edward
0
 
LVL 86

Expert Comment

by:jkr
ID: 10892662
>>Pure virtual

You cannot instantiate classes that have pure virtual members. You need to at least derive a class that implements these.
0
 

Author Comment

by:edwardt
ID: 11046476
Hi guys,

At the end I did end up making the copy constructors for a few classes, and it was very useful.

Thanks!

Axter - Another set of points for you to split. I'll create a question for that.

-Edward
0
 
LVL 12

Expert Comment

by:stefan73
ID: 11051470
Hi Axter,
You forgot the good old NULL as a classic use for pointers :)

Cheers,
Stefan
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Unlike C#, C++ doesn't have native support for sealing classes (so they cannot be sub-classed). At the cost of a virtual base class pointer it is possible to implement a pseudo sealing mechanism The trick is to virtually inherit from a base class…
What is C++ STL?: STL stands for Standard Template Library and is a part of standard C++ libraries. It contains many useful data structures (containers) and algorithms, which can spare you a lot of the time. Today we will look at the STL Vector. …
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now