Download presentation
Presentation is loading. Please wait.
1
cstring Library Access with #include Or the C way, #include Provides two sets of functions for dealing with strings
2
C-Style String Functions The str* functions work with C-style strings A few examples –strcpy - copies strings –strcat - concatenates two strings –strcmp - compares two strings
3
strlen The most used of the str* functions Returns the length of a string It is declared as: size_t strlen(const char *str);
4
strcpy and strncpy Copies a string char* strcpy(char *dest, const char *src); char* strncpy*char *dest, const char *src, size_t n); If the length is unknown use strncpy
5
strcat and strncat Concatenates two strings char* strcat(char *dest, const char *src); char* strncat(char *dest, const char *src, size_t n); Again, use strncat if you don’t know the length
6
strcmp and strncmp Compares two strings int strcmp(const char *s1, const char *s2); int strncmp(const char *s1, const char *s2, size_t n); Use strncmp to compare just the first n characters Returns 0 (false) if the strings are the same!
7
#include int main() { const char *s1 = “The first string”; const char *s2 = “The second string”; if (std::strcmp(s1,s2) == 0) std::cout << “Strings the same\n”; else if (std::strcmp(s1,s2) < 0) std::cout << “s1 less than s2\n”; else std::cout << “s2 less than s1\n”; }
8
memory functions The mem* functions work with known length strings (arrays of chars) Instead of using a nul terminator A few examples: –memcpy - copies an array –memchr - find a char in an array –memcmp - compares two arrays
9
memcpy Copies a memory area void* memcpy(void *dest, const void *src, size_t n); Can be used to copy any memory area int array1[] = {1,2,3,4}; int array2[10]; std::memcpy(array1,array2,sizeof(int)*4);
10
strlen implementation size_t strlen(const char *str) { size_t count = 0; while (str[count] != ‘\0’) count++; return count; } size_t strlen(const char *str) { const char *s; for(s=str;*s;s++) /*nothing*/; return s - str; }
11
Structures A struct is an heterogeneous aggregate of types struct person { char name[80]; char phone[20]; unsigned short age; }; int main() { Person p; std::strcpy(p.name,”Johhny”); std::strcpy(p.phone,”99999999”); p.age = 30; }
12
Object Oriented C++ C++ is hybrid language - it allows Object Oriented Code, Procedural Code, and Generic Code We’ll look at the OO style of C++ OO in C++ is just classes and objects
13
Class Syntax A class is just like a struct. class Person { public : Person(string name); Person(const Person&); Person& operator=(const Person&); ~Person(); string get_name(); private: string name; };
14
Classes in C++ C++ is a reasonably low level OO object You have to do more to write a class than in a language like Java There are three basic functions you need to provide: –A way to create objects of the class –A way to copy objects of the class –A way to discard objects of the class
15
Constructors Objects are created from classes by constructors Constructors are defined like methods –they have no return type –they have the same name as the class Constructors are often used by the compiler to create objects implicitly
16
Default Constructor The default constructor is a constructor that takes no arguments If you do not write any constructors the compiler will create a default constructor –it will set members to their ‘default’ values Default constructors are used by the C++ libraries so it is wise to have one if possible Write it yourself - unless efficiency is vital
17
Copy Constructor The copy constructor is a constructor which is passed an object of the class If you don’t write a copy constructor the compiler will provide one –it will just copy the values of the members Used by the compiler and libraries so if possible one should be provided Write it yourself - unless efficiency is vital
18
Destructor Objects are discarded by the destructor It is defined just like a method –it has no return type –it has the name of the class prefixed with ~ The destructor should free any resources the object is using The compiler will provide a do nothing destructor if you don’t write one
19
Assignment Operator We’ll look at operator overloading later Most classes should have an assignment operator written Foo& operator=(const Foo&); It is called whenever an object is assigned to another (Foo a; Foo b; a = b;) Writing one is usually a mechanical process we’ll look at soon
20
A Linked List We’ll look at a simple linked list class to see how classes are written If you actually need a list you are much better off using the one provided by the STL
21
struct Node; //we’ll define this later class List { public: List(); // Default constructor List(const List&); // copy constructor List& operator=(const List&); //assign operator ~List(); // destructor int length(); void insert_at_front(int value); bool insert_after_current(int value); void delete_first(); void delete_after_current(); void set_current_to_front(); void advance_current(); int get_current_value(); bool check_current_in_list(); private: Node *head; Node *current; };
22
Default Constructor Should construct a default valued list We’ll make that an empty list List::List() { head = 0; current = 0; } Can also write it inside the class definition: List() : head(0), current(0) {}
23
Copy Constructor List::List(const List& o) { if (o.head == 0) { head = current = 0; } else { head = new Node(*(o.head)); current = 0; for (Node *c1=head,*c2=o.head; c2->next;c1=c1->next;c2=c2->next) { c1->next=new Node(*(c2->next)); if (o.current == c2) current = c1; } };
24
Destructor List::~List() { Node *current = head; while (current) { Node *remove = current; current = current->next; delete remove; }
25
Assignment Operator Normally an assignment operator does the following: –Check for equivalence –destroy the current object –copy the object across –return a reference to the object (to allow chaining)
26
List& List::operator=(const List &o) { if (this == &orig) return *this; Node *current = head; while (current) { Node *remove = current; current = current->next; delete remove; } if (o.head == 0) { head = current = 0; } else { head = new Node(*(o.head)); current = 0;
27
for (Node *c1=head,*c2=o.head; c2->next;c1=c1->next;c2=c2->next) { c1->next = new Node(*c2->next); if (o.current == c2) current = c1; } return *this; }
28
Member Functions Also known as methods Perform operations on the object Must always leave the object in a consistent state
29
length int List::length() { int len = 0; for(Node *c=head;c;c=c->next) count++; return count; }
30
insert_at_front void List::insert_at_front(int value){ Node *node = new Node; node->number = value; node->next = head; head = node; }
31
insert_after_current bool List::insert_after_current(int value) { if (current == 0) return false; Node *node = new Node; node->number = value; node->next = current->next; current->next = node; return true; }
32
delete_first void List::delete_first() { if (head==0) return; Node *remove = head; head = head->next; if (current == remove) current = 0; delete remove; }
33
delete_after_current void List::delete_after_current() { if (current==0 || current->next==0) return; Node *remove = current->next; current->next = current->next->next; delete remove; }
34
set_current_to_front void List::set_current_to_front() { current = head; }
35
advance_current void List::advance_current() { if (current == 0) return; current = current->next; }
36
get_current_value int List::get_current_value() { if (current == 0) return 0; return current->number; }
37
check_current_in_list bool List::check_current_in_list() { return current != 0; }
38
The Node Struct In writing the List class some assumptions about the Node struct were made Now we have to write the Node struct so that those assumptions are met
39
Node struct Node { int number; Node *next; Node() : number(0),next(0){}; Node(const Node &o) : number(o.number),next(0) {}; };
40
Memory Management C++ does not have a garbage collector The programmer much manually manage memory Memory needs to be allocated when needed It must be deallocated when not needed Not managing memory correctly is a major source of bugs in C++ code
41
C++ Memory Model Memory can be allocated from the stack or the heap Variables are allocated on the stack That memory is automatically deallocated Objects can be created on the heap with new That memory can be deallocated with delete
42
Allocating Memory new creates an object on the heap The appropriate constructor is called new[] creates an array on the heap The default constructor is called for each element of the array int *i_array = new int[100]; string *a_string = new string(“fred”);
43
Deallocating Memory delete calls an objects destructor The memory used is then released delete[] calls the destructor of each element of an array The memory used is then released Every object created with new must be deleted Every array created with new[] must be delete[]ed
44
More of the story new and delete don’t just manage memory They also call constructors and destructors Other resources are also allocated and released File handles, network connections, and file locks must be released along with memory
45
More about main() main can be passed arguments int main(int argc, char **argv); int main(int argc, char *argv[]); This allows a program to access the command line arguments So a text editor can know what file to open
46
main() example #include int main(int argc, char **argv) { for(int i=0;i<argc;i++) std::cout << argv[i] << std::endl; }
47
Functions You can have many functions with the same name They just need different arguments This is very useful, but can get confusing
48
Example Functions void foo(int val) { std::cout << “int\n”; } void foo(char c) { std::cout << “char\n”; } int main() { int I; char c; long l; foo( i ); foo( c ); foo( l ); }
49
Function Resolution C++ will often call functions implicitly in order to compile your code This is very useful since it means you can often write simpler code It is also dangerous since sometimes you don’t get what you meant It can also make code hard to understand
50
An Example class Complex { public:Complex(int re=0, int im=0); }; int distance( const Complex &a, const Complex &b); int main() { distance(1,2); }
51
Classes as Types C++ allows you to create classes which act like built-in types Operator overloading is the tool for this It can be used for both good and evil Do not overuse it Do use it for output via ostream objects
52
Output via operator overloading class List { friend ostream& operator<<(ostream &os, const List &list); }; ostream& operator<<(ostream &os, const List &list) { for (Node *c=list.head;c;c=c->next) os number << ‘ ‘; }
53
Inheritance Inheritance in C++ is a little complicated The default behaviour is often not what you want The default behaviour is usually the most efficient behaviour not the most useful
54
class Warning_Indicator { public: void turn_on() { std::cout << “Indicator on\n”; } }; class Warning_Buzzer { public: void turn_on() { std::cout << “Buzzer on\n”; } }; void alarm(Warning_Indicator wi) { wi.turn_on(); } int main() { Warning_Buzzer buzzer; alarm(buzzer); }
55
A problem What does alarm(buzzer) do? It is known as slicing - it is usually an error The compiler creates a Warning_Indicator object via it’s Copy Constructor from the Warning_Buzzer The fix is to pass a reference instead of an Object: void alarm(const Warning_Indicator &wi);
56
More Problems The program will still output “Indicator on” Now the problem is due to binding C++ defaults to compile time binding wi.turn_on() becomes a call to the turn_on member function of Warning_Indicator Even when a Warning_Buzzer is used, the Warning_Indicator member is called
57
The Solution The solution is to use run time binding In C++ that is done with the keyword virtual class Warning_Indicator { public: virtual void turn_on(); };
58
Virtual A virtual function takes more time to call An object with virtual functions takes up more memory The actual function to call is looked up at run time Looking up takes time Storing the function in the object takes space
59
Accessibility and Inheritance private members can only be accessed by the class itself (and friends) protected members can also be accessed by classes that inherit from the class That is almost always a bad thing It prevents implementation changes later - the main benefit or OO programming
60
class Base { public : i; protected : j; private : k; }; class Child : public Base { public: void test() { i = 1; // legal j = 1; // illegal k = 1; // illegal } };
61
Constructors and Inheritance If a base class has a constructor then it must be called By default the default constructor is called If you want to call a different constuctor then you need to use an initialiser
62
class Person { public: Person(const string& name); }; class Student : public Person { public: Student(const string& name, const string& sid) : Person(name) { } };
63
Destructors and Inheritance Destructors are automatically called However, if a class is to inherited from its destructor must be declared virtual Not doing so can result in resource leaks Person *p = new Student(”Sam”,”9222194”); delete p;
64
Abstract Classes Seperating interface and implementation is often wise In C++ you can do this with abstract classes An abstract class is one with at least one pure virtual function
65
An Abstract Example class Security_Device { public: virtual turn_on() = 0; virtual turn_off() = 0; virtual is_on() = 0; };
66
Multiple Inheritance C++ supports multiple inheritance Sometimes useful, but leads to problems Problems occur with diamond inheritance trees Multiple inheritance will not be needed for this course
67
Non-public Inheritance class B : private A –public and protected members of A are treated as private –this applies to users of B, but not B itself class B : protected A –public members of A are treated as protected This allows implementation inheritance without interface inheritance
Similar presentations
© 2025 SlidePlayer.com Inc.
All rights reserved.