assignment overloading

I'm trying to write a program that uses the stack ADT with a linked list implementation. I can't seem to overload the assignment operator. I keep getting an error that says

"StackClass::Pop cannot convert 'this' pointer from 'const StackClass' to 'StackClass&'"

All of my other methods are working correctly, but let me know if you need more



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void StackClass::operator =(const StackClass& orig)
{
	Clear();

	StackClass temp;
        
	while(!orig.IsEmpty())
	{
		temp.Push(orig.Retrieve());

		orig.Pop();
	}//end while


	while(!temp.IsEmpty())
	{
		Push(temp.Retrieve());

		temp.Pop();
	}//end while

}
You are calling a non-const method on a const reference. That's not permitted.
The assignment doesn't look right. When one uses assignment, one doesn't expect the right-hand operator to be modified, yet here it's being emptied.
What you should do is access the members yourself, instead of relying on the methods.
I changed the parameter and it does what I want it to now

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void StackClass::operator =(StackClass orig)
{
	Clear();

	StackClass temp;
        
	while(!orig.IsEmpty())
	{
		temp.Push(orig.Retrieve());

		orig.Pop();
	}//end while


	while(!temp.IsEmpty())
	{
		Push(temp.Retrieve());

		temp.Pop();
	}//end while

}
Well, orig is now a copy of the parameter object, so you don't need temp in there.

Surely there is a better way to do the assignment than this.
How is the copy constructor implemented? The assignment should look practically the same.
In fact, lately I've been implementing the two like this:
1
2
3
4
5
6
7
8
9
10
11
12
class A{
	//members
public:
	A::A(const A &b){
		//initializations
		(*this)=b;
	}
	A &operator=(const A &b){
		//delete all dynamically allocated members
		//perform assignments
	}
};
Last edited on
This is the entire .cpp and .h files, this is the one that give problems because I'm trying to modify a const in the operator=, I know I can't modify orig, but I really can't think of what to do. I either end up with the previous error message, or I get one about infinite recursion.

helios - when I originally learned c++, I was told that *this returns a shallow copy so my copy constructor isn't going to do what I want it to.

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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#include<cstdlib>

typedef int KeyType;

struct ItemType		
{					
	KeyType key;		
};


struct node;


class StackClass

{
  public:
			
	StackClass(); 
	
	StackClass(const StackClass& orig);

	~StackClass();

	bool IsEmpty() const; 

	bool IsFull() const;	

	void Push(/*in*/ItemType newItem);

	void Pop();	

	ItemType Retrieve() const;
   
	void Clear();

	virtual void operator =(const StackClass& orig);

 private:

   node* stack; 


protected:
   node* Allocate();



};  // end StackClass


StackClass::StackClass()
{	
	stack = NULL;

}  // end default constructor

StackClass::StackClass(const StackClass& orig)
{
	stack = NULL;
	operator=(orig);
}

StackClass::~StackClass()
{
	Clear();
}
bool StackClass::IsEmpty() const
{
  
	return(stack == NULL);

}//end IsEmpty
bool StackClass::IsFull() const
{

	return false;

} // end IsFull

ItemType StackClass::Retrieve() const
{

	return stack->data;

}  // end Retrieve

void StackClass::Push(/*in*/ItemType newItem)//newItem is the item to be inserted
								
{				
	node* temp;
	
	if(!IsFull())
	{
		temp = Allocate();
		temp->data = newItem;
		temp->next = stack;
		stack = temp;
	}


}// end Push

void StackClass::Pop()
{
	node* temp;

	if(!IsEmpty())
	{
		temp = stack;
		stack = stack->next;
		delete temp;
	}//end if


}  // end Pop

void StackClass::Clear() 
{

	while(!IsEmpty())
		Pop();

}//end Clear
void StackClass::operator =(const StackClass& orig)
{
	Clear();

	StackClass temp;

	while(!orig.IsEmpty())
	{
		temp.Push(orig.Retrieve());

		orig.Pop();
	}//end while


	while(!temp.IsEmpty())
	{
		Push(temp.Retrieve());

		temp.Pop();
	}//end while

}//end operator=

node* StackClass::Allocate()
{
	
	node* temp = new node;

	if(temp == NULL)
	{
		exit(999);
	}
	
	else
	{
		temp->next = NULL;
	
		return temp;
	}

}//end Allocate 


You probably want your copy constructor to walk the nodes manually and create new nodes in the new object that are copies from the original.

Then -- create a swap() method:

1
2
3
4
void StackClass::swap(StackClass& other)
{
    std::swap(stack, other.stack);
}


And then implement your operator=() in terms of the second method outlined here:

http://en.wikipedia.org/wiki/Assignment_operator_in_C%2B%2B

It's called the no-fail swap method and makes creating assignment operators a breeze. But there may still be complexity in the copy constructor.
when I originally learned c++, I was told that *this returns a shallow copy so my copy constructor isn't going to do what I want it to.
No. this is a pointer to the object that calls the member. Therefore, *this is the object itself. Doing *this=b is no different from doing *pointer=object. In my example, line 6 is calling A::operator=(), so it's equivalent to what you did on line 61.
If that's how your copy constructor was implemented when you posted
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void StackClass::operator =(StackClass orig)
{
	Clear();

	StackClass temp;
        
	while(!orig.IsEmpty())
	{
		temp.Push(orig.Retrieve());

		orig.Pop();
	}//end while


	while(!temp.IsEmpty())
	{
		Push(temp.Retrieve());

		temp.Pop();
	}//end while

}
then that would have caused infinite recursion.
+1 for PanGalactic's solution.

Topic archived. No new replies allowed.