system programming practical session 9 c++ classes
Post on 20-Dec-2015
216 views
TRANSCRIPT
Outline
• STL examples
• Basic concepts
• Classes that hold pointers
• Destructor
• Copy constructor
• Operator=
void bad_clean_odd(std::vector<int> &vec){
for (std::vector<int>::iterator iter = vec.begin(); iter != vec.end(); ++iter){
if (*iter % 2 != 0)vec.erase(iter); // @@BAD! After the call to erase, iter is invalid.
}}
void clean_odd(std::vector<int> &vec){
std::vector<int>::iterator iter = vec.begin();while (iter != vec.end()){
if (*iter % 2 == 0)iter++;
elseiter = vec.erase(iter);
}}int main(){
std::vector<int> vec; while(std::cin){ int i; //assume stdin holds only integers! std::cin >> i; vec.push_back(i); }
clean_odd(vec); for (std::vector<int>::iterator iter = vec.begin(); iter != vec.end(); ++iter) std::cout << *iter << std::endl; return 0;}
int main(){std::map<std::string,int> stringCounts;std::string str;
while( std::cin >> str ){ std::map<std::string,int>::iterator found =
stringCounts.find(str);if (found != stringCounts.end())
found->second++;else
stringCounts.insert(std::make_pair(str, 1));}
std::map<std::string,int>::iterator iter; for( iter = stringCounts.begin(); iter != stringCounts.end(); ++iter) {
std::cout << "word: " << iter->first << ", count: " << iter->second << std::endl;
}
return 0;}
class Cow{private: int _id;public: Cow(int id): _id(id) {} int getId() const {return _id;}}
// A comparator is a class that implements the operator()// It is passed as a parameter to the priority queue// and used to perform the comparisons among items in the queue.class CowComparator { public: bool operator()(const Cow &x, const Cow &y) { // return true if x < y, false otherwise return x.getId() < y.getId(); }}int main(){ typedef std::priority_queue<Cow, std::vector<Cow>, CowComparator> PrioQueue; PrioQueue queue; while(std::cin) { int id; // assume stdin holds only ints std::cin >> id; queue.push(Cow(id)); } while(! queue.empty()){ std::cout << queue.top().getId() << std::endl; queue.pop();
}}
template <typename T>bool from_string(T& t, const std::string& s, std::ios_base& (*f)(std::ios_base&) = std::dec){ std::istringstream iss(s); return !(iss >> f >> t).fail();} template <typename T>std::string to_string(const T& t){ std::ostringstream o; o << t; return o.str();} //usage example:int main(){ std::vector<int> vec; std::string line; while(std::cin >> line){ int i; if (! from_string(i, line)){ std::cerr << "Please input only ints!!" << std::endl; continue; } vec.push_back(i); }}
C++ simple class example1. // THE DECLARATION FILE OF THE CLASS POINT (Point.h)
2. class Point
3. {
4. public:
5. Point();
6. Point(double xval, double yval);
7. void move(double dx, double dy);
8. double getX() const;
9. double getY() const;
10. private:
11. double _x;
12. double _y;
13. };
C++ simple class example1. // THE IMPLEMENTATION FILE OF CLASS POINT (Point.cpp)
2. #include "Point.h"
3. Point::Point():_x(0), _y(0){ }
4. Point::Point(double xval, double yval):_x(xval),_y(yval){}
5. void Point::move(double dx, double dy) {
6. _x = _x + dx;
7. _y = _y + dy;
8. }
9. double Point::getX() const {
10. return _x;
11.}
12.double Point::getY() const {
13. return _y;
14.}
C++ simple class exampleUse example1. #include <iostream>
2. #include “point.h”
3. int main( ){
4. Point p(0,0);
5. //Point p;
6. p.move(10,15);
7. const Point p2(20,12);
8. std::cout << p2.getx() << std::endl;
9. std::cout << p2.gety() << std::endl;
10. // p2.move(1,1); compilation error since move is not declared const
11.}
Member Initialization Listclass Circle{
public:
Circle(); Circle(double centerX, double centerY, double radius); ………….. private:
Point _center;
double _radius;
};
Circle::Circle(): _center(0,0) , _radius(1) {}
Circle::Circle(double centerX, double centerY, double radius): _center(centerX, centerY) , _radius(radius) {}
Member Initialization List
Rules• The initial value can be any expression.
• The order the initialization happens is according to the order the member variables are declared.
• The member initialization list is executed before the body of the constructor.
•Not initializing a member via the initialization list means implicitly calling its default constructor
• Const members of a class can only be initialized via member initialization list.
Example: Circle::Circle(): _center(0,0) , _radius(1) {}
InheritanceSyntax: class Derived : public Base { };
#include “point.h”
#include “color.h” // suppose that we have defined class Color…
class Pixel : public Point{
Color _color;
……
};
Pixel::Pixel(Point point, Color color) : Point(point), _color(color) {}
// example of a derived constructor calling the base constructor
// Syntax: Derived::Derived(….) : Base(….) {…}
Operator>-
Shortcut for accessing members of an object pointed by a pointer.
ptr->member is a shortcut for (*ptr).member
1. class Point{.....}
2. int main( ){
3. Point *p1=new Point(0,0);
4. Point p2(0,0);
5. p1->getX();
6. (*p1).getX();
7. p2.getX();
8. (&p2)->getX();
9. }
Objects• In C++, object variables hold values, not object references.
• When one object is assigned to another, a copy of the actual values is made.
•When modifying an object in a function, you must remember to use call by reference.
•Two object variables cannot jointly access one object. If you need this effect in C++, then you need to use pointers.
•An object variable can only hold values of a particular type. If you want a variable to hold objects from different subclasses, you need to use pointers.
•If you want a variable point to either null or to an actual object, then you need to use pointers in C++.
Classes that hold pointers
A class that has a pointer data member should include the following member functions:
1. A virtual destructor
2. A copy constructor
3. operator= (assignment)
Link1. class Link {
2. private:
3. Link* next_;
4. std::string data_;
5. public:
6. Link(const std::string& data, Link* link);
7. Link(const Link& aLink); //copy constructor
8. virtual ~Link(); // destructor
9. void setNext(Link* link);
10. Link* getNext() const;
11. const std::string& getData() const;
12.};
1. Link::Link(const std::string& data, Link* link) : data_(data) {
2. setNext(link);
3. }
4. void Link::setNext(Link* link) {
5. next_=link;
6. }
7. Link* Link::getNext() const {
8. return next_;
9. }
10. const std::string& Link::getData() const {
11. return data_;
12. }
13. Link::~Link() { } \\destructor
14. Link::Link(const Link& aLink) { \\copy constructor
15. data_=aLink.getData();
16. next_=0;
17. }
Link
List1. class List { 2. private: 3. Link* head_; 4. Link* copy() const; 5. void clear(); 6. 7. public: 8. List(); 9. const Link* getHead() const; 10. void insertData(const std::string& data); 11. void removeFirst(); 12. 13. List(const List& aList); 14. virtual ~List(); 15. List& operator=(const List &L); 16.};
1. List::List() : head_(0) { } 2. const Link* List::getHead() const{ 3. return head_; 4. } 5. void List::insertData(const std::string& data){ 6. head_ = new Link(data, head_); 7. }8. void List::removeFirst(){ 9. if (0 != head_) { 10. Link* tmp = head_; 11. head_ = head_->getNext(); 12. delete tmp; 13. } 14. } 15. List::~List() { 16. clear(); 17. } 18. void List::clear(){ 19. while (0 != head_) { 20. removeFirst(); 21. } 22. }
23. Link* List::copy() const { 24. if (0 == getHead()) return 0; 25. else { 26. Link *head = new Link(*getHead()); 27. Link *next = head; 28. for (Link *origPtr = getHead()->getNext(); 0 !
= origPtr; 29. origPtr = origPtr->getNext()) { 30. next->setNext(new Link(*origPtr)); 31. next = next->getNext(); 32. } 33. return head; 34. } } 35. List::List(const List &aList){ 36. head_ = aList.copy(); 37. } 38. List & List::operator=(const List &L) { 39. if (this == &L) 40. return *this; 41. clear(); 42. head_ = L.copy(); 43. return *this; 44. }
Destructor
An object's destructor function is called when that object is about to "go away“.
• For local variables (objects declared on the stack) and value parameters – When the variable goes out of scope.
• For dynamically allocated storage (objects on the heap) –
When the programmer frees the storage using delete.
Destructor1. void f(List L) {
2. List *p = new List();
3. while (...) {
4. List L1;
5. ...
6. }
7. delete p;
8. }
Is a destructor function of a reference parameter called at the end of the function? No!
1. /**
2. * Destructor: "deep delete"
3. */
4. List::~List() {
5. clear();
6. }
7. void List::removeFirst()
8. {
9. if (0 != head_) {
10. Link* tmp = head_;
11. head_ = head_->getNext();
12. delete tmp;
13. }
14.}
15. void List::clear(){
16. while (0 != head_) {
17. removeFirst();
18. }
19.}
Copy Constructor An object's copy constructor is called (automatically, not by the
programmer) when it is created, and needs to be initialized to be a copy of an existing object.
This happens when an object is:
• Passed as a value parameter to a function,
1. Point q(2,2); Point p(0,0);
2. p.moveTo(q); //moveTo(Point point)
• Returned (by value) as a function result,
• Declared with initialization from an existing object of the same class.
1. void f(Point p){
2. Point temp=p;
3. Point temp2(p);
4. …
1. List f( List L );
2. int main() {
3. List L1, L2;
4. ...
5. L2 = f( L1 ); // copy constructor called here to copy L1
6. }
7. List f( List L ) {
8. List tmp1 = L; // copy constructor called here to copy L
9. List tmp2(L); // copy constructor called here to copy L
10. ...
11. return tmp1; // copy constructor called here
12.}
Example
Copy Constructor Declaration
1. class List {
2. public:
3. ……
4. List(const List &L);// copy constructor
5. ...
6. };
Copy Constructor Definition1. List::List(const List &aList){
2. head_ = aList.copy();
3. }
4. Link* List::copy() const {
5. if (0 == getHead()) return 0;
6. else {
7. Link *head = new Link(*getHead());
8. Link *next = head;
9. for (Link *origPtr = getHead()->getNext();
10. 0 != origPtr; origPtr = origPtr->getNext()) {
11. next->setNext(new Link(*origPtr));
12. next = next->getNext();
13. }
14. return head;
15. }
16.}
Operator=
• By default, class assignment is just a field-by-field assignment
• If a class includes pointer fields, the default assignment operator causes aliasing which lead to trouble!
Solution: overload operator= to perform deep copy.
Syntax:
List & operator=(const List &L);
Note that operator= differs from the copy constructor in three important ways:
• The object being assigned to has already been initialized; therefore, if it has a pointer field, the storage pointed to must be freed to prevent a storage leak.
• It is possible for a programmer to assign from a variable into itself; for example: L1 = L1. The operator= code must check for this case, and do nothing.
• The operator= code must return a value
Operator=
Definition of operator= It should always include the following 4 sections:
• check assignment to self
• clear existing data members
• copy data member from other
• return this 1. List & List::operator=(const List &L) {
2. if (this == &L) {
3. return *this;
4. }
5. clear();
6. head_ = L.copy();
7. return *this;
8. }