Operator Overloading and Dynamic Memory within a class

Hello all,

This is a lab exercise for homework due tomorrow, and I'm trying to figure out how to code Person.cpp. Person.h and Main.cpp are from my teacher and need no modification. Any help is very apperciated. :)


Person.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <string>
using std::string;

#include <iostream>
using std::ostream;
using std::istream;

#ifndef PERSON_H
#define PERSON_H

class Person{
	friend ostream& operator << (ostream& lvalue, const Person& rvalue);
	friend istream& operator >> (istream& lvalue, Person& rvalue);

public:
	Person(); // constructor
	~Person(); // destructor
	explicit Person(const Person&); // copy constructor
	Person& operator = (const Person&); // assignment operator (Person&)
	string getName() const; // accessor
	void setName(const string&); // mutator
private:
	string* name;
};
#endif 


Main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#ifdef _DEBUG
#define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
#define new DEBUG_NEW
#endif

#include <iostream>
using std::cout;
using std::cin;
using std::endl;

#include <sstream>
using std::stringstream;

#include "Person.h"

int main()
{
	_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
	{
		// test default constructor
		Person* p1Ptr = new Person;
		
		// test copy constructor
		Person* p2Ptr = new Person(*p1Ptr);
		
		// test insertion operator
		cout << *p1Ptr << endl; // empty string will print
		cout << *p2Ptr << endl; // empty string will also print
		
		// test setName
		p1Ptr->setName("Sally");
		
		// test getName
		cout << p1Ptr->getName() << endl << endl; // Sally
		
		// test extraction operator
		cout << "Please enter a name for p1Ptr: ";
		cin >> *p1Ptr;
		cout << *p1Ptr << endl; // user entry will print
		
		// test assignment operator Person = Person
		*p2Ptr = *p1Ptr;
		cout << *p2Ptr << endl; // should match user entry
		
		// test destructor
		delete p1Ptr;
		delete p2Ptr;
		
		Person* persons[5];
		stringstream ss;
		for(int i = 0; i < 5; i++)
		{
			persons[i] = new Person();
			ss.str(""); // clears the ss (like a setString)
			ss << "Name " << i;
			persons[i]->setName(ss.str()); // ss.str() is like a getString
		}
		
		for(int j = 0; j < 5; j++)
		{
			cout << persons[j]->getName() << endl;
		}
		
		for(int k = 0; k < 5; k++)
		{
			delete persons[k];
		}
	}
	_CrtDumpMemoryLeaks();
	system("PAUSE");
	return 0;
}



Person.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include "Person.h"

#include <iostream>
using std::cout;
using std::endl;

ostream& operator<<(ostream& lhs, const Person& rhs) 
{
	lhs << *rhs.name;
	return lhs;
}

istream& operator>>(istream& lhs, Person& rhs) 
{
	lhs >> *rhs.name;
	return lhs;
}

Person::Person()
{
	*name = "Undefined";
}

Person::~Person()
{
	cout << "destructor" << endl;
}

Person::Person(const Person& p)
{
	name = p.name;
}

Person& Person::operator = (const Person& p)
{
	cout << "assignment operator=(Double)" << endl;
	if(this == &p){ return *this; }
	this->name = p.name;
	return *this;
}

string Person::getName() const
{
	return *name;
}

void Person::setName(const string& newName)
{
	*name = newName;
}
Very nice.

So what's the problem?
I think the problem is that professor has violated some basic rules of C++: just look at those
using clauses in the header file!
Disch (3669) Nov 5, 2010 at 12:07am
Very nice.

So what's the problem?


I have no idea what this means....

>c:\users\jason\documents\visual studio 2010\projects\labexercise07\labexercise07\main.cpp(31): error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'Person' (or there is no acceptable conversion)
1>          c:\program files (x86)\microsoft visual studio 10.0\vc\include\ostream(679): could be 'std::basic_ostream<_Elem,_Traits> &std::operator <<<char,std::char_traits<char>>(std::basic_ostream<_Elem,_Traits> &,const char *)' [found using argument-dependent lookup]
1>          with
1>          [
1>              _Elem=char,
1>              _Traits=std::char_traits<char>
1>          ]
In line 23 of Person.h you are given a string*. You need to allocate some memory for it in the constructor using new string;. Don't forget to delete it in the destructor.

+1 jsmith, crazy header file...
So how do I use new string? I think in person.h file it's a pointer pointing to nothing. So how would I make it modify the variable string name that's not a pointer?? could anyone write an example with my code, it would be greatly apperciated

1
2
3
4
Person::Person()
{
      name = new string;
}


Like that?

But now I can't figure out what's wrong with

Main.cpp
1
2
3
// test insertion operator
cout << *p1Ptr << endl; // empty string will print
cout << *p2Ptr << endl; // empty string will also print 
Last edited on
Your constructor is now correct. Don't forget to delete the string in your destructor.

Your insertion operator looks fine to me.

You can't do your copy constructor like that. You will end up with both copies pointing at the same string. You need to assign a new string with new and copy.
Last edited on
Thanks everyone,

I think everything is good! no errors and no memory leaks :)

Person.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include "Person.h"

#include <iostream>
using std::cout;
using std::endl;

ostream& operator<<(ostream& lhs, const Person& rhs) 
{
    lhs << *rhs.name;
    return lhs;
}

istream& operator>>(istream& lhs, Person& rhs) 
{
    lhs >> *rhs.name;
    return lhs;
}

Person::Person()
{
   name = new string;
}

Person::~Person()
{
  delete name;
}

Person::Person(const Person& p)
{
   name = new string;
}

Person& Person::operator = (const Person& p)
{
    if(this == &p){ return *this; }
    *this->name = *p.name;
    return *this;
}

string Person::getName() const
{
   return *name;
}

void Person::setName(const string& newName)
{
   *name = newName;
}
your copy constructor is still wrong. You allocate the memory which is good. But you don't copy the parameter's string into yours.
Last edited on
Topic archived. No new replies allowed.