classes with dynamic objects list as a (dynamic) class
Post on 21-Dec-2015
233 views
TRANSCRIPT
Classes with dynamic objects
List as a (dynamic) class
int x;
void f() {
x=10;
}
main() {
x=0;
f();
}
‘Class’ matters!
int x;
void f() {
int x;
x=10;
}
main() {
x=0;
f();
}
class A {
public
int x;
void f();
}
main() {
A a;
a.x = 0;
a.f();
}
localglobal public
class A {
public:
void f();
int x;
private:
int y;
}
void A::f() {
x=10;
y=100;
}
int main() {
A a;
a.f();
cout << a.x << endl;
cout << a.y << endl; // no!!!
a.x = 1000;
a.y = 10000; // no!!!
}
Public or private?
class A {
public:
A();
int f();
private:
int x;
}
A::A() {
x=0;
}
int A::f() {
return x;
}
int main()
{
A a;
cout << a.f(); // not a.x!!!
A b(a);
A c;
c = a; // member-wise copy
}Objects are calling member funtions
(public interface)
Member functions are using member variables (private data)
Objects are not directly dependent on implementation (private data)
Abstract Data Type: public function, private data
Static variables (objects) Dynamic variables (objects)
A (direct) named memory location A static part (pointer) + (indirect) nameless memory location
(dynamic part)int a;
a = 20;int* pa;
pa = new int;
*pa = 20;
20a 20pa
static static dynamic
Static and dynamic
Only static member variablesAt least one pointer variable (I.e.
dynamic variable)
class A {
public:
A();
private:
int x;
}
class B {
public:
B();
B(const B& b);
~B();
private:
int* px;
}
(Must) a defaut value constructor A() for
‘copy constructor’ automatically privided
No destructor
‘assignment’ automatically provided
(Must) a defaut value constructor for
(Must) redefine ‘copy constructor’
(Must) the destructor
(Must) redefine ‘assignment’ (do later)
initialisation Creation by new + initialiation
classes
class B {
public:
B();
B(const B& b);
~B();
private:
int* px;
}
B::B() {
px = new int;
*px = 0;
}
B::B(const B& b) {
px = new int;
(*px) = *(b.px);
}
B::~B() {
delete px;
}
All constructors/destructor have automatic behavior, they are called ‘implicitly’!!! (that’s why they have standard names!)
Constructors are called when creating variables and other occasions:
Destructors are called when the variables go out of scope
A a; // implicitly call the default value constructor A::A();
A b(a); // implicitly call the copy constructor A::A(const A& a);
Automatic behavior of constructors/destructor
void somefunction() {
B b;
};
Example of a (dynamic) class: linked list class
bool listEmpty(NodePtr head) {
}int getHead(NodePtr head) {
}NodePtr getRest(NodePtr head) {
}NodePtr addHead(NodePtr head, int newdata) {
}void delHead(NodePtr& Head){
}
linked lists: definition
struct Node{ int data;Node* next;
};
typedef Node* NodePtr;
NodePtr head;
void main(){
NodePtr Head1=NULL, Head2 = NULL, Head;
addHead(Head1, 50);
addHead(Head1, 40);
addHead(Head1, 30);
addHead(Head1, 20);
cout << "List 1: " << endl;
DisplayList(Head1);
cout << "Length of Head1 list: " << length(Head1) << endl;
cout << "Recursive length of Head1 list: " << lengthRec(Head1) << endl;
if(isPalindrome(Head1))
cout << "Head1 list is palindrome" << endl;
else
cout << "Head1 list is not palindrome" << endl;
addHead(Head2, 25);
addHead(Head2, 35);
addHead(Head2, 45);
addHead(Head2, 35);
addHead(Head2, 25);
cout << "List 2: " << endl;
DisplayList(Head2);
cout << "Length of Head2 list: " << length(Head2) << endl;
cout << "Recursive length of Head2 list: " << lengthRec(Head2) << endl;
if(isPalindrome(Head2))
cout << "Head2 list is palindrome" << endl;
else
cout << "Head2 list is not palindrome" << endl;
Head = mergeLists(Head1, Head2);
cout << "Merged List: " << endl;
DisplayList(Head);
cout << "Length of Merged list: " << length(Head) << endl;
cout << "Recursive length of Merged list: " << lengthRec(Head) << endl;
if(isPalindromeRec(Head))
cout << "Merged list is palindrome" << endl;
else
cout << "Merged list is not palindrome" << endl;
cout << "check the list again:" << endl;
DisplayList(Head);
}
Usage:
Make an Abstract Data Type
One more example of ADT: integer linked list using class
A class with dynamic objects: Copy constructor Destructor
struct Node{ public:
int data;Node* next;
};typedef Node* Nodeptr;
class list {public:
list(); // constructorlist(const list& list1); // copy constructor~list(); // destructor
bool empty() const; // boolean functionint headElement() const; // access functions
void addHead(int newdata); // add to the headvoid deleteHead(); // delete the head
int length() const; // utility functionvoid print() const; // output
private:Nodeptr head;
};‘old’ operations
‘new’ member functions
void main(){list L; // constructor called automatically here for LL.print(); { }L.addHead(30);L.print(); { 30 }L.addHead(13);L.print(); { 13 30 } L.addHead(40);L.print(); { 40 13 30 }L.addHead(50);L.print(); { 50 40 13 30 }list N(L);N.print(); { 50 40 13 30 }
list R;R.print(); { }if(R.empty())
cout << "List R empty" << endl;L.deleteHead();L.print(); { 40 13 30 }L.deleteHead();L.print(); { 13 30 }if(L.empty())
cout << "List L empty" << endl;else{
cout << "List L contains " << L.length() << " nodes" << endl;cout << "Head element of list L is: " << L.headElement() << endl;
}} // destructor called automatically here for L
How to use it
list::list(){head = NULL;
}
bool list::empty() const{if(head==NULL)
return true;else
return false;}
int list::headElement() const {if(head != NULL)
return head->data;else{
cout << "error: trying to find head of empty list" << endl;
exit(1);}
}
Some simple member functions:
Implementation
list::list(const list& list1) {
head = NULL;
Nodeptr cur = list1.head;
while(cur != NULL) {
// addEnd(cur->data);
addHead(cur->data); // inverse list order
cur = cur->next;
}
}
(explicitly defined) copy constructor:
Destructor: deallocation function
list::~list(){
Nodeptr cur;
while(head!=NULL){
cur = head;
head = head->next;
delete cur;
}
}
void list::addHead(int newdata){
Nodeptr newPtr = new Node;
newPtr->data = newdata;
newPtr->next = head;
head = newPtr;
}
Adding an element to the head:
void list::deleteHead(){
if(head != NULL){
Nodeptr cur = head;
head = head->next;
delete cur;
}
}
Deleting the head:
void list::print() const{cout << "{";Nodeptr cur = head;while(cur != NULL){
cout << cur->data << " ";
cur = cur->next;}
cout << "}" << endl;}
Print the list:
int list::length() const{
int n=0;Nodeptr cur = head;while(cur != NULL){
n++;cur = cur->next;
}return n;
}
Computing the number of elements of a given list:
struct Node{ public:
int data;Node* next;
};typedef Node* Nodeptr;
class list {public:
list(); // constructorlist(const list& list1); // copy constructorconst list& operator=(const list& list1); // assigment, l = l1;~list(); // destructor
bool empty() const; // boolean functionint head() const; // access functionslist remaining() const; // the list with the head removed void insert(int d); // insertionvoid delete(int d); // deletion
int length() const; // utility functionvoid print() const; //
private:Nodeptr head;
};
Interface functions
An almost ideal list class
list::list(const listClass& list1) {
head = NULL;
Nodeptr cur = list1.head;
while(cur != NULL) {
// addEnd(cur->data);
addHead(cur->data); // inverse list order
cur = cur->next;
}
}
copy constructor:
Const list& operator=(const list& list1) {
if (this != &list1) {
head = NULL;
Nodeptr cur = list1.head;
while(cur != NULL) {
// addEnd(cur->data);
addHead(cur->data); // inverse list order
cur = cur->next;
}
return *this;
}
Operator assignment, ‘deep copy’
Delete[] head;
Big three: copy constructor, operator=, destructor
list l1, l2;
l1.addEnd(5);
list l3(l1);
l3 = l2;
node* head1, head2;
head1 = NULL; head2 = NULL
addEnd(head1,5);
node* head3 = NULL;
copylist(head1, head3);
head3 = head2;
Usage difference