SlideShare uma empresa Scribd logo
1 de 59
Baixar para ler offline
6.088 Intro to C/C++

    Day 6: Miscellaneous Topics


     Eunsuk Kang & Jean Yang
In the last lecture...

Inheritance

Polymorphism

Abstract base classes
Today’s topics
Polymorphism (again)

Namespaces

Standard Template Library

Copying objects

Integer overflow
Polymorphism revisited
Polymorphism revisited
Recall: Ability of type A to appear as or be used like
another type B.

Example:
Rectangle* r = new Square(5.0);   // length = 5.0



where Square is a subtype of Rectangle
Liskov Substitution Principle
Photograph removed due to copyright restrictions.
Please see http://www.pmg.csail.mit.edu/~liskov/.
                                                                       .




                                                    Barbara Liskov
                                                    Winner,Turing Award 08’


              If S is a subtype of T, then the behavior of
              a program P must remain unchanged
              when objects of type T are replaced with
              objects of type S.
Rectangle-Square example 

class Rectangle {
  protected:

   float length;

   float width;

  public:

   Rectangle(float length, float width);

   void setLength();

   void setWidth();

   void getLength();

   void getWidth();

}

class Square : public Rectangle {
  // representation invariant: length = width

  public:
   Square(float length);
   void setLength(); // ensures length = width
   void setWidth();   // does nothing
}
Rectangle-Square example

class Rectangle {
  protected:

   float length;

   float width;

  public:

   Rectangle(float length, float width);

   void setLength();

   void setWidth();                  Violates the Liskov

   void getLength();
   void getWidth();                 Substitution Principle.
}
                                            Why?
class Square : public Rectangle {
  // representation invariant: length = width
  public:
   Square(float length);

   void setLength(); // ensures length = width

   void setWidth();   // does nothing

}
Solutions
Ugly: Modify setWidth and setLength in Rectangle to
return a boolean. Make them return “true” in
Rectangle, and “false” in Square. Define a separate
method “setDimension” in Square.

Better: Maybe Square shouldn’t really be a subtype of
Rectangle? Change the type hierarchy!
Think about behaviors, not just characteristics of an
object!
Solutions
Ugly: Modify setWidth and setLength in Rectangle to
return a boolean.They always return “true” in
Rectangle, and “false” in Square. Define a separate
method “setDimension” in Square.

Better: Maybe Square shouldn’t really be a subtype of
Rectangle? Re-think the type hierarchy!
Think about behaviors, not just characteristics of an
object!
Solutions
Ugly: Modify setWidth and setLength in Rectangle to
return a boolean.They always return “true” in
Rectangle, and “false” in Square. Define a separate
method “setDimension” in Square.

Better: Maybe Square shouldn’t really be a subtype of
Rectangle? Re-think the type hierarchy!
Think about behaviors, not just characteristics of an
object!
Namespaces
Namespaces
�an abstract space that contains a set of names

�useful for resolving naming conflicts
namespace ford {
  class SUV {
    ...
  };
}
namespace dodge {
  class SUV {
    ...
  };
}

int main() {
  ford::SUV s1 = new ford::SUV();
  dodge::SUV s2 = new dodge::SUV();
  ...
}
Using namespaces

Use with caution!
namespace ford {
  class SUV {
    ...

  };

  class Compact {

    ...
  };
}

int main() {
  using namespace ford;   // exposes SUV and Compact
  SUV s1 = new SUV();
  ...
}
Using namespaces
Expose only the things that you need to use!

namespace ford {
  class SUV {
    ...

  };

  class Compact {

    ...
  };
}

int main() {
  //using namespace ford;
  using ford::SUV;
  SUV s1 = new SUV();
  ...
}
C++ standard library & namespace

C++ standard library includes:
�string (std:string s = “Hello   World!”)
�vector (std::vector<T> ...)
�iostream (std::cout << ...)
�and many other things!
The library lives inside the namespace “std”
Using namespace std 

#include <string>

class MITPerson {

 protected:
  int id;
  std::string name;
  std::string address;

 public:

     MITPerson(int id, std::string name, std::string address);

     void displayProfile();
     void changeAddress(std::string newAddress);

};
Using namespace std 

#include <string>

class MITPerson {

 protected:
  int id;
  std::string name;
  std::string address;

 public:

     MITPerson(int id, std::string name, std::string address);

     void displayProfile();
     void changeAddress(std::string newAddress);

};
Using namespace std 

#include <string>

class MITPerson {

protected:
 int id;
 std::string name;
             I am too lazy to type!
 std::string address;


 public:


     MITPerson(int id, std::string name, std::string address);


     void displayProfile();

     void changeAddress(std::string newAddress); 


};
Using namespace std 

#include <string>

using namespace std;

class MITPerson {

 protected:
  int id;
  string name;
  string address;

 public:

     MITPerson(int id, string name, string address);

     void displayProfile();
     void changeAddress(string newAddress);

};
Using namespace std - Be aware!
This is potentially dangerous.Why?

Rules of thumb:
�“using std::string” instead of “using namespace std”
�include “using...” only in the .cc file, not in the header
(why?)

Simplest rule: Just type “std::”. Sacrifice a few extra
keystrokes in the name of good!
Standard Template
Library
Standard Template Library (STL)
�a set of commonly used data structures & algorithms

�parameterized with types
Some useful ones include:
�vector
�map
�stack, queue, priority_queue
�sort
More available at:
http://www.cppreference.com/wiki/stl/start
Example using vectors

�an array with automatic resizing

std::vector<T> v;   // creates an empty vector of type T elements 


std::vector<int> v2(100); 
// creates a vector with 100 ints

std::vector<T> v3(100); 
// creates a vector with 100 elements




     primitives initialized to        objects created using 

      some default value               default constructor
Student class from the last lecture

#include   <iostream>
#include   <vector>
#include   "MITPerson.h"
#include   "Class.h"

class Student : public MITPerson {

     int course;

     int year;     // 1 = freshman, 2 = sophomore, etc.

     std::vector<Class*> classesTaken;


 public:
  Student(int id, std::string name, std::string address,
         int course, int year);

  void displayProfile();

  void addClassTaken(Class* newClass);

  void changeCourse(int newCourse);


};
A list of classes as a vector

#include   <iostream>
#include
#include
           <vector>
           "MITPerson.h"
                             don’t forget!
#include   "Class.h"

class Student : public MITPerson {

  int course;
  int year;     // 1 = freshman, 2 = sophomore, etc.
  std::vector<Class*> classesTaken;

 public:
  Student(int id, std::string name, std::string address,
         int course, int year);
  void displayProfile();
  declares an empty vector of
  void addClassTaken(Class* newClass);

                            pointers to Class objects
  void changeCourse(int newCourse);

};
Vector operations 

Class* c1 = new Class(“6.01”);

Class* c2 = new Class(“6.005”); 


// inserting a new element at the back of the vector
classesTaken.push_back(c1);

classesTaken.push_back(c2);


// accessing an element

Class* c3 = classesTaken[0];

Class* c4 = classesTaken.at(1);

std::cout << c3.getName() << “n”;   // prints “6.01”

std::cout << c4.getName() << “n”;   // prints “6.005” 


// removing elements from the back of the vector

classesTaken.pop_back();

classesTaken.pop_back();


// checking whether the vector is empty

if (classesTaken.empty()) std::cout << “Vector is empty!n”;
Vector operations 

Class* c1 = new Class(“6.01”);

Class* c2 = new Class(“6.005”); 


// inserting a new element at the back of the vector
classesTaken.push_back(c1);

classesTaken.push_back(c2);


// accessing an element

Class* c3 = classesTaken[0];

Class* c4 = classesTaken.at(1);

std::cout << c3.getName() << “n”;   // prints “6.01”

std::cout << c4.getName() << “n”;   // prints “6.005” 


// removing elements from the back of the vector

classesTaken.pop_back();

classesTaken.pop_back();


// checking whether the vector is empty

if (classesTaken.empty()) std::cout << “Vector is empty!n”;
Vector operations 

Class* c1 = new Class(“6.01”);

Class* c2 = new Class(“6.005”); 


// inserting a new element at the back of the vector
classesTaken.push_back(c1);

classesTaken.push_back(c2);


// accessing an element

Class* c3 = classesTaken[0];

Class* c4 = classesTaken.at(1);

std::cout << c3.getName() << “n”;   // prints “6.01”

std::cout << c4.getName() << “n”;   // prints “6.005” 


// removing elements from the back of the vector

classesTaken.pop_back();

classesTaken.pop_back();


// checking whether the vector is empty
if (classesTaken.empty()) std::cout << “Vector is empty!n”;
Vector operations 

Class* c1 = new Class(“6.01”);

Class* c2 = new Class(“6.005”); 


// inserting a new element at the back of the vector
classesTaken.push_back(c1);

classesTaken.push_back(c2);


// accessing an element

Class* c3 = classesTaken[0];

Class* c4 = classesTaken.at(1);

std::cout << c3.getName() << “n”;   // prints “6.01”

std::cout << c4.getName() << “n”;   // prints “6.005” 


// removing elements from the back of the vector

classesTaken.pop_back();

classesTaken.pop_back();


// checking whether the vector is empty
if (classesTaken.empty()) std::cout << “Vector is empty!n”;
Traversing a vector using an iterator

// display a list of classes taken by the student

// create an iterator
std::vector<Class*>::iterator it;

std::cout << "Classes taken:n";

// step through every element in the vector
for (it = classesTaken.begin(); it != classesTaken.end(); it++){
  Class* c = *it;
  std::cout << c->getName() << "n";
}

Classes taken:
6.01
6.005
Traversing a vector using an iterator

// display a list of classes taken by the student
                                    type for the iterator
// create an iterator
std::vector<Class*>::iterator it;
                                         increment iterator
std::cout << "Classes taken:n";

// step through every element in the vector
for (it = classesTaken.begin(); it != classesTaken.end(); it++){
  Class* c = *it;
  std::cout << c->getName() << "n";
}




  iterator to the beginning                iterator to the end
        of the vector                         of the vector
Traversing a vector using an iterator

// display a list of classes taken by the student

// create an iterator
std::vector<Class*>::iterator it;

std::cout << "Classes taken:n";

// step through every element in the vector
for (it = classesTaken.begin(); it != classesTaken.end(); it++){
  Class* c = *it;
  std::cout << c->getName() << "n";
}



     it a pointer to an element
     *it the element
There are many other functions





            Courtesy of C++ Reference. Used with permission.

http://www.cppreference.com/wiki/stl/vector/start
Copying objects
Objects as values
So far we’ve dealt mostly with pointers to objects. 


What if you want to pass around objects by value?
For example,
void print(MITPerson p){
  p.displayProfile();
}

int main() {
  MITPerson p1(921172, “James Lee”, “32 Vassar St.”);
  MITPerson p2 = p1;
  print(p2);
}



                                     36
Creating an object from another
                  1. initialization by value, so make a copy
void print(MITPerson p){
  p.displayProfile();
}

int main() {
                       2. pass by value, so make a copy
  MITPerson p1(921172, “James Lee”, “32 Vassar St.”);
  MITPerson p2 = p1;
  print(p2);
}




   (3. could also return an object as a return value)

                               37
Copying objects using constructors

void print(MITPerson p){
  p.displayProfile();
}

int main() {
  MITPerson p1(921172, “James Lee”, “32 Vassar St.”);
  MITPerson p2 = p1;
  print(p2);
}


So how do objects get copied?

Copy constructors are called.

Object::Object(const Object& other) {
  ...
}

                               38
Copy constructor in MITPerson

#include <string>

class MITPerson {

protected:
 int id;
 std::string name;
 std::string address;

public:

  MITPerson(int id, std::string name, std::string address);
  MITPerson(const MITPerson& other);

  void displayProfile();
  void changeAddress(std::string newAddress);
};


                               39
Defining the copy constructor

               why const?            object that you are
                                        copying from

MITPerson::MITPerson(const MITPerson& other){
  name = other.name;
  id = other.id;
  address = other.address;
}




                               40
Default copy constructor
�automatically generated by the compiler
�copies all non-static members (primitives & objects)

�invokes the copy constructor of member objects
MITPerson::MITPerson(const MITPerson& other){
  name = other.name;
  id = other.id;
  address = other.address;
}




                               41
Assigning an object to another

MITPerson p1(921172, “James Lee”, “32 Vassar St.”);
MITPerson p2(978123, “Alice Smith”, “121 Ames St.”);
p2 = p1; // assigns p2 to p1, does NOT create a new object


So how do objects get assigned to each other?
Copy assignment operator is called.
Object& Object::operator=(const Object& other) {
  ...
}




                               42
Copy assignment operator in MITPerson

#include <string>

class MITPerson {

 protected:

  int id;

  std::string name;

  std::string address;


 public:

  MITPerson(int id, std::string name, std::string address);
  MITPerson(const MITPerson& other);

  MITPerson& operator=(const MITPerson& other);
   void displayProfile();
   void changeAddress(std::string newAddress);
};

                               43
Defining the copy assignment operator

MITPerson& MITPerson::operator=(const MITPerson& other){
  name = other.name;
  id = other.id;
  address = other.address;

    return *this;   // returns a newly assigned MITPerson
}

MITPerson p1(921172, “James Lee”, “32 Vassar St.”);
MITPerson p2(978123, “Alice Smith”, “121 Ames St.”);
p2 = p1;




                                  44
Defining the copy assignment operator 

MITPerson& MITPerson::operator=(const MITPerson& other){
  name = other.name;
  id = other.id;
  address = other.address;

    return *this;
}


Again, if you don’t define one, the compiler will
automatically generate a copy assignment operator

So why do we ever need to define copy constructors &
copy assignment operators ourselves?

                               45
Default copy constructor - caution!

class B {
 public:
  void print() { std::cout << "Hello World!n”; }
};

class A {
  B* pb;
  int x;
 public:

  A(int y) : x (y) { pb = new B(); }

  ~A() { delete pb; } // destructor

  void printB() { pb->print(); }

};

void foo(A a) {
  a.printB();
}

int main() {
  A a1(5);
  a1.printB();
  foo(a1);
  return 0;
}

                                             46
Default copy constructor - caution!

class B {
 public:
  void print() { std::cout << "Hello World!n”; }
};

class A {
  B* pb;
  int x;
 public:

  A(int y) : x (y) { pb = new B(); }

  ~A() { delete pb; } // destructor
                                                 Double free!
};
  void printB() { pb->print(); }
                                               How do we fix this?
void foo(A a) {
  a.printB();
}

int main() {
  A a1(5);
  a1.printB();
  foo(a1);
  return 0;
}

                                             47
Default copy constructor - caution!

class B {
 public:
  void print() { std::cout << "Hello World!n”; }
};

class A {
   B* pb;
   int x;
 public:

   A(int y) : x (y) { pb = new B(); }

  A(const A& other) { // copy constructor

     x = other.x;

     pb = new B();

  }
  ~A() { delete pb; } // destructor
  A& operator=(const A& other) { // copy assignment operator
     x = other.x;
     delete pb;                    // clean up the junk in the existing object!
     pb = new B();
     return *this;
  }
  void printB() { pb->print(); }
};


                                             48
Rule of three in C++
If you define any one of the three in a class, then you

should define all three (you will probably need them!)


�destructor
�copy constructor
�copy assignment operator




                          49
Integer overflow
Binary search algorithm

int binarySearch(int a[], int key, int length) {
  int low = 0;
  int high = length - 1;

    while (low <= high) {

      int mid = (low + high) / 2;

      int midVal = a[mid];


      if (midVal < key) 

        low = mid + 1

      else if (midVal > key)

        high = mid - 1;

      else

        return mid;      // key found

    }

    return -(low + 1);   // key not found

}                                             Courtesy of Joshua Bloch. Used with permission.



based on from Joshua Bloch’s implementation in java.util

                                         51
Binary search bug

int binarySearch(int a[], int key, int length) {
  int low = 0;
  int high = length - 1;

    while (low <= high) {

      int mid = (low + high) / 2;

      int midVal = a[mid];


      if (midVal < key) 

         low = mid + 1
                    Can you find the bug?
       else if (midVal > key)

         high = mid - 1;

       else

         return mid;      // key found

    }

    return -(low + 1); // key not found

                                             Courtesy of Joshua Bloch. Used with permission.
}




                                       52
Binary search bug

int binarySearch(int a[], int key, int length) {
  int low = 0;
  int high = length - 1;

    while (low <= high) {
      int mid = (low + high) / 2;
      int midVal = a[mid];
                                         if (low + high) > MAX_INTEGER,
                                                   it will overflow!
      if (midVal < key) 

        low = mid + 1
                   dangerous array access!
      else if (midVal > key)
                                         (Java will at least throw
       high = mid - 1;
      else                                    an exception)
        return mid;      // key found

    }

    return -(low + 1);   // key not found

                                                Courtesy of Joshua Bloch. Used with permission.
}




                                         53
One solution 

Instead of:
int mid = (low + high) / 2;


use:

int mid = low + (high - low) / 2;



Surprisingly, most implementations of the binary
search tree had this bug! (including java.util)

http://googleresearch.blogspot.com/2006/06/extra­
extra-read-all-about-it-nearly.html
                                54
Conclusion
Useful links
Google C++ style guideline

http://google-styleguide.googlecode.com/svn/trunk/
cppguide.xml

C++ FAQ

http://www.parashift.com/c++-faq-lite/index.html




                         56
There are many things we haven’t told you!

Thinking in C++ (B. Eckel) Free online edition!


Essential C++ (S. Lippman)


Effective C++ (S. Meyers)


C++ Programming Language (B. Stroustrup)


Design Patterns (Gamma, Helm, Johnson,Vlissides)


Object-Oriented Analysis and Design with 

Applications (G. Booch, et. al)

                               57
Congratulations!

Now you know enough about C/C++ to 

   embark on your own journey!





                58
MIT OpenCourseWare
http://ocw.mit.edu




6.088 Introduction to C Memory Management and C++ Object-Oriented Programming
January IAP 2010




For information about citing these materials or our Terms of Use, visit: http://ocw.mit.edu/terms.

Mais conteúdo relacionado

Mais procurados

Generic Programming seminar
Generic Programming seminarGeneric Programming seminar
Generic Programming seminar
Gautam Roy
 
DIDUCE: ICSE-2002 presentation
DIDUCE: ICSE-2002 presentationDIDUCE: ICSE-2002 presentation
DIDUCE: ICSE-2002 presentation
hangal
 

Mais procurados (20)

2java Oop
2java Oop2java Oop
2java Oop
 
Modern C++ Explained: Move Semantics (Feb 2018)
Modern C++ Explained: Move Semantics (Feb 2018)Modern C++ Explained: Move Semantics (Feb 2018)
Modern C++ Explained: Move Semantics (Feb 2018)
 
Scala Type Classes: Basics and More
Scala Type Classes:  Basics and MoreScala Type Classes:  Basics and More
Scala Type Classes: Basics and More
 
Generic Programming seminar
Generic Programming seminarGeneric Programming seminar
Generic Programming seminar
 
Templates exception handling
Templates exception handlingTemplates exception handling
Templates exception handling
 
constructors and destructors in c++
constructors and destructors in c++constructors and destructors in c++
constructors and destructors in c++
 
iOS Basic
iOS BasiciOS Basic
iOS Basic
 
Java generics
Java genericsJava generics
Java generics
 
Introduction to Objective - C
Introduction to Objective - CIntroduction to Objective - C
Introduction to Objective - C
 
Objective c slide I
Objective c slide IObjective c slide I
Objective c slide I
 
Objective-C for iOS Application Development
Objective-C for iOS Application DevelopmentObjective-C for iOS Application Development
Objective-C for iOS Application Development
 
Classes and object
Classes and objectClasses and object
Classes and object
 
Algorithm and Programming (Array)
Algorithm and Programming (Array)Algorithm and Programming (Array)
Algorithm and Programming (Array)
 
Multiple file programs, inheritance, templates
Multiple file programs, inheritance, templatesMultiple file programs, inheritance, templates
Multiple file programs, inheritance, templates
 
DIDUCE: ICSE-2002 presentation
DIDUCE: ICSE-2002 presentationDIDUCE: ICSE-2002 presentation
DIDUCE: ICSE-2002 presentation
 
Semmle Codeql
Semmle Codeql Semmle Codeql
Semmle Codeql
 
Idiomatic C++
Idiomatic C++Idiomatic C++
Idiomatic C++
 
Extending javascript part one
Extending javascript part oneExtending javascript part one
Extending javascript part one
 
Container Classes
Container ClassesContainer Classes
Container Classes
 
First-Class Patterns
First-Class PatternsFirst-Class Patterns
First-Class Patterns
 

Destaque

麻省理工C++公开教学课程(一)
麻省理工C++公开教学课程(一)麻省理工C++公开教学课程(一)
麻省理工C++公开教学课程(一)
ProCharm
 
麻省理工C++公开教学课程(二)
麻省理工C++公开教学课程(二)麻省理工C++公开教学课程(二)
麻省理工C++公开教学课程(二)
ProCharm
 
电子杂志(试刊)
电子杂志(试刊)电子杂志(试刊)
电子杂志(试刊)
ProCharm
 

Destaque (7)

麻省理工C++公开教学课程(一)
麻省理工C++公开教学课程(一)麻省理工C++公开教学课程(一)
麻省理工C++公开教学课程(一)
 
麻省理工C++公开教学课程(二)
麻省理工C++公开教学课程(二)麻省理工C++公开教学课程(二)
麻省理工C++公开教学课程(二)
 
电子杂志(试刊)
电子杂志(试刊)电子杂志(试刊)
电子杂志(试刊)
 
麻省理工C++公开教学课程(三)
麻省理工C++公开教学课程(三)麻省理工C++公开教学课程(三)
麻省理工C++公开教学课程(三)
 
What's Next in Growth? 2016
What's Next in Growth? 2016What's Next in Growth? 2016
What's Next in Growth? 2016
 
The Outcome Economy
The Outcome EconomyThe Outcome Economy
The Outcome Economy
 
32 Ways a Digital Marketing Consultant Can Help Grow Your Business
32 Ways a Digital Marketing Consultant Can Help Grow Your Business32 Ways a Digital Marketing Consultant Can Help Grow Your Business
32 Ways a Digital Marketing Consultant Can Help Grow Your Business
 

Semelhante a 麻省理工C++公开教学课程(二)

Chapter27 polymorphism-virtual-function-abstract-class
Chapter27 polymorphism-virtual-function-abstract-classChapter27 polymorphism-virtual-function-abstract-class
Chapter27 polymorphism-virtual-function-abstract-class
Deepak Singh
 
Chapter 6.6
Chapter 6.6Chapter 6.6
Chapter 6.6
sotlsoc
 
Unit 1 Part - 3 constructor Overloading Static.ppt
Unit 1 Part - 3  constructor Overloading Static.pptUnit 1 Part - 3  constructor Overloading Static.ppt
Unit 1 Part - 3 constructor Overloading Static.ppt
DeepVala5
 
c++-language-1208539706757125-9.pdf
c++-language-1208539706757125-9.pdfc++-language-1208539706757125-9.pdf
c++-language-1208539706757125-9.pdf
nisarmca
 
Chapter 13 introduction to classes
Chapter 13 introduction to classesChapter 13 introduction to classes
Chapter 13 introduction to classes
rsnyder3601
 
C# for C++ programmers
C# for C++ programmersC# for C++ programmers
C# for C++ programmers
Mark Whitaker
 

Semelhante a 麻省理工C++公开教学课程(二) (20)

Java tutorial for Beginners and Entry Level
Java tutorial for Beginners and Entry LevelJava tutorial for Beginners and Entry Level
Java tutorial for Beginners and Entry Level
 
Chapter27 polymorphism-virtual-function-abstract-class
Chapter27 polymorphism-virtual-function-abstract-classChapter27 polymorphism-virtual-function-abstract-class
Chapter27 polymorphism-virtual-function-abstract-class
 
Introduce oop in python
Introduce oop in pythonIntroduce oop in python
Introduce oop in python
 
Defining classes-and-objects-1.0
Defining classes-and-objects-1.0Defining classes-and-objects-1.0
Defining classes-and-objects-1.0
 
Cocoa for Web Developers
Cocoa for Web DevelopersCocoa for Web Developers
Cocoa for Web Developers
 
Chapter 6.6
Chapter 6.6Chapter 6.6
Chapter 6.6
 
C++ Language
C++ LanguageC++ Language
C++ Language
 
Java Generics
Java GenericsJava Generics
Java Generics
 
Basics of objective c
Basics of objective cBasics of objective c
Basics of objective c
 
Unit 1 Part - 3 constructor Overloading Static.ppt
Unit 1 Part - 3  constructor Overloading Static.pptUnit 1 Part - 3  constructor Overloading Static.ppt
Unit 1 Part - 3 constructor Overloading Static.ppt
 
c++-language-1208539706757125-9.pdf
c++-language-1208539706757125-9.pdfc++-language-1208539706757125-9.pdf
c++-language-1208539706757125-9.pdf
 
Chapter 13 introduction to classes
Chapter 13 introduction to classesChapter 13 introduction to classes
Chapter 13 introduction to classes
 
Writing good code
Writing good codeWriting good code
Writing good code
 
Java Concepts
Java ConceptsJava Concepts
Java Concepts
 
Csphtp1 10
Csphtp1 10Csphtp1 10
Csphtp1 10
 
3433 Ch10 Ppt
3433 Ch10 Ppt3433 Ch10 Ppt
3433 Ch10 Ppt
 
Java02
Java02Java02
Java02
 
C# for C++ programmers
C# for C++ programmersC# for C++ programmers
C# for C++ programmers
 
Inheritance in C++.ppt
Inheritance in C++.pptInheritance in C++.ppt
Inheritance in C++.ppt
 
Core java concepts
Core java  conceptsCore java  concepts
Core java concepts
 

麻省理工C++公开教学课程(二)

  • 1. 6.088 Intro to C/C++ Day 6: Miscellaneous Topics Eunsuk Kang & Jean Yang
  • 2. In the last lecture... Inheritance Polymorphism Abstract base classes
  • 3. Today’s topics Polymorphism (again) Namespaces Standard Template Library Copying objects Integer overflow
  • 5. Polymorphism revisited Recall: Ability of type A to appear as or be used like another type B. Example: Rectangle* r = new Square(5.0); // length = 5.0 where Square is a subtype of Rectangle
  • 6. Liskov Substitution Principle Photograph removed due to copyright restrictions. Please see http://www.pmg.csail.mit.edu/~liskov/. . Barbara Liskov Winner,Turing Award 08’ If S is a subtype of T, then the behavior of a program P must remain unchanged when objects of type T are replaced with objects of type S.
  • 7. Rectangle-Square example class Rectangle { protected: float length; float width; public: Rectangle(float length, float width); void setLength(); void setWidth(); void getLength(); void getWidth(); } class Square : public Rectangle { // representation invariant: length = width public: Square(float length); void setLength(); // ensures length = width void setWidth(); // does nothing }
  • 8. Rectangle-Square example class Rectangle { protected: float length; float width; public: Rectangle(float length, float width); void setLength(); void setWidth(); Violates the Liskov void getLength(); void getWidth(); Substitution Principle. } Why? class Square : public Rectangle { // representation invariant: length = width public: Square(float length); void setLength(); // ensures length = width void setWidth(); // does nothing }
  • 9. Solutions Ugly: Modify setWidth and setLength in Rectangle to return a boolean. Make them return “true” in Rectangle, and “false” in Square. Define a separate method “setDimension” in Square. Better: Maybe Square shouldn’t really be a subtype of Rectangle? Change the type hierarchy! Think about behaviors, not just characteristics of an object!
  • 10. Solutions Ugly: Modify setWidth and setLength in Rectangle to return a boolean.They always return “true” in Rectangle, and “false” in Square. Define a separate method “setDimension” in Square. Better: Maybe Square shouldn’t really be a subtype of Rectangle? Re-think the type hierarchy! Think about behaviors, not just characteristics of an object!
  • 11. Solutions Ugly: Modify setWidth and setLength in Rectangle to return a boolean.They always return “true” in Rectangle, and “false” in Square. Define a separate method “setDimension” in Square. Better: Maybe Square shouldn’t really be a subtype of Rectangle? Re-think the type hierarchy! Think about behaviors, not just characteristics of an object!
  • 13. Namespaces �an abstract space that contains a set of names �useful for resolving naming conflicts namespace ford { class SUV { ... }; } namespace dodge { class SUV { ... }; } int main() { ford::SUV s1 = new ford::SUV(); dodge::SUV s2 = new dodge::SUV(); ... }
  • 14. Using namespaces Use with caution! namespace ford { class SUV { ... }; class Compact { ... }; } int main() { using namespace ford; // exposes SUV and Compact SUV s1 = new SUV(); ... }
  • 15. Using namespaces Expose only the things that you need to use! namespace ford { class SUV { ... }; class Compact { ... }; } int main() { //using namespace ford; using ford::SUV; SUV s1 = new SUV(); ... }
  • 16. C++ standard library & namespace C++ standard library includes: �string (std:string s = “Hello World!”) �vector (std::vector<T> ...) �iostream (std::cout << ...) �and many other things! The library lives inside the namespace “std”
  • 17. Using namespace std #include <string> class MITPerson { protected: int id; std::string name; std::string address; public: MITPerson(int id, std::string name, std::string address); void displayProfile(); void changeAddress(std::string newAddress); };
  • 18. Using namespace std #include <string> class MITPerson { protected: int id; std::string name; std::string address; public: MITPerson(int id, std::string name, std::string address); void displayProfile(); void changeAddress(std::string newAddress); };
  • 19. Using namespace std #include <string> class MITPerson { protected: int id; std::string name; I am too lazy to type! std::string address; public: MITPerson(int id, std::string name, std::string address); void displayProfile(); void changeAddress(std::string newAddress); };
  • 20. Using namespace std #include <string> using namespace std; class MITPerson { protected: int id; string name; string address; public: MITPerson(int id, string name, string address); void displayProfile(); void changeAddress(string newAddress); };
  • 21. Using namespace std - Be aware! This is potentially dangerous.Why? Rules of thumb: �“using std::string” instead of “using namespace std” �include “using...” only in the .cc file, not in the header (why?) Simplest rule: Just type “std::”. Sacrifice a few extra keystrokes in the name of good!
  • 23. Standard Template Library (STL) �a set of commonly used data structures & algorithms �parameterized with types Some useful ones include: �vector �map �stack, queue, priority_queue �sort More available at: http://www.cppreference.com/wiki/stl/start
  • 24. Example using vectors �an array with automatic resizing std::vector<T> v; // creates an empty vector of type T elements std::vector<int> v2(100); // creates a vector with 100 ints std::vector<T> v3(100); // creates a vector with 100 elements primitives initialized to objects created using some default value default constructor
  • 25. Student class from the last lecture #include <iostream> #include <vector> #include "MITPerson.h" #include "Class.h" class Student : public MITPerson { int course; int year; // 1 = freshman, 2 = sophomore, etc. std::vector<Class*> classesTaken; public: Student(int id, std::string name, std::string address, int course, int year); void displayProfile(); void addClassTaken(Class* newClass); void changeCourse(int newCourse); };
  • 26. A list of classes as a vector #include <iostream> #include #include <vector> "MITPerson.h" don’t forget! #include "Class.h" class Student : public MITPerson { int course; int year; // 1 = freshman, 2 = sophomore, etc. std::vector<Class*> classesTaken; public: Student(int id, std::string name, std::string address, int course, int year); void displayProfile(); declares an empty vector of void addClassTaken(Class* newClass); pointers to Class objects void changeCourse(int newCourse); };
  • 27. Vector operations Class* c1 = new Class(“6.01”); Class* c2 = new Class(“6.005”); // inserting a new element at the back of the vector classesTaken.push_back(c1); classesTaken.push_back(c2); // accessing an element Class* c3 = classesTaken[0]; Class* c4 = classesTaken.at(1); std::cout << c3.getName() << “n”; // prints “6.01” std::cout << c4.getName() << “n”; // prints “6.005” // removing elements from the back of the vector classesTaken.pop_back(); classesTaken.pop_back(); // checking whether the vector is empty if (classesTaken.empty()) std::cout << “Vector is empty!n”;
  • 28. Vector operations Class* c1 = new Class(“6.01”); Class* c2 = new Class(“6.005”); // inserting a new element at the back of the vector classesTaken.push_back(c1); classesTaken.push_back(c2); // accessing an element Class* c3 = classesTaken[0]; Class* c4 = classesTaken.at(1); std::cout << c3.getName() << “n”; // prints “6.01” std::cout << c4.getName() << “n”; // prints “6.005” // removing elements from the back of the vector classesTaken.pop_back(); classesTaken.pop_back(); // checking whether the vector is empty if (classesTaken.empty()) std::cout << “Vector is empty!n”;
  • 29. Vector operations Class* c1 = new Class(“6.01”); Class* c2 = new Class(“6.005”); // inserting a new element at the back of the vector classesTaken.push_back(c1); classesTaken.push_back(c2); // accessing an element Class* c3 = classesTaken[0]; Class* c4 = classesTaken.at(1); std::cout << c3.getName() << “n”; // prints “6.01” std::cout << c4.getName() << “n”; // prints “6.005” // removing elements from the back of the vector classesTaken.pop_back(); classesTaken.pop_back(); // checking whether the vector is empty if (classesTaken.empty()) std::cout << “Vector is empty!n”;
  • 30. Vector operations Class* c1 = new Class(“6.01”); Class* c2 = new Class(“6.005”); // inserting a new element at the back of the vector classesTaken.push_back(c1); classesTaken.push_back(c2); // accessing an element Class* c3 = classesTaken[0]; Class* c4 = classesTaken.at(1); std::cout << c3.getName() << “n”; // prints “6.01” std::cout << c4.getName() << “n”; // prints “6.005” // removing elements from the back of the vector classesTaken.pop_back(); classesTaken.pop_back(); // checking whether the vector is empty if (classesTaken.empty()) std::cout << “Vector is empty!n”;
  • 31. Traversing a vector using an iterator // display a list of classes taken by the student // create an iterator std::vector<Class*>::iterator it; std::cout << "Classes taken:n"; // step through every element in the vector for (it = classesTaken.begin(); it != classesTaken.end(); it++){ Class* c = *it; std::cout << c->getName() << "n"; } Classes taken: 6.01 6.005
  • 32. Traversing a vector using an iterator // display a list of classes taken by the student type for the iterator // create an iterator std::vector<Class*>::iterator it; increment iterator std::cout << "Classes taken:n"; // step through every element in the vector for (it = classesTaken.begin(); it != classesTaken.end(); it++){ Class* c = *it; std::cout << c->getName() << "n"; } iterator to the beginning iterator to the end of the vector of the vector
  • 33. Traversing a vector using an iterator // display a list of classes taken by the student // create an iterator std::vector<Class*>::iterator it; std::cout << "Classes taken:n"; // step through every element in the vector for (it = classesTaken.begin(); it != classesTaken.end(); it++){ Class* c = *it; std::cout << c->getName() << "n"; } it a pointer to an element *it the element
  • 34. There are many other functions Courtesy of C++ Reference. Used with permission. http://www.cppreference.com/wiki/stl/vector/start
  • 36. Objects as values So far we’ve dealt mostly with pointers to objects. What if you want to pass around objects by value? For example, void print(MITPerson p){ p.displayProfile(); } int main() { MITPerson p1(921172, “James Lee”, “32 Vassar St.”); MITPerson p2 = p1; print(p2); } 36
  • 37. Creating an object from another 1. initialization by value, so make a copy void print(MITPerson p){ p.displayProfile(); } int main() { 2. pass by value, so make a copy MITPerson p1(921172, “James Lee”, “32 Vassar St.”); MITPerson p2 = p1; print(p2); } (3. could also return an object as a return value) 37
  • 38. Copying objects using constructors void print(MITPerson p){ p.displayProfile(); } int main() { MITPerson p1(921172, “James Lee”, “32 Vassar St.”); MITPerson p2 = p1; print(p2); } So how do objects get copied? Copy constructors are called. Object::Object(const Object& other) { ... } 38
  • 39. Copy constructor in MITPerson #include <string> class MITPerson { protected: int id; std::string name; std::string address; public: MITPerson(int id, std::string name, std::string address); MITPerson(const MITPerson& other); void displayProfile(); void changeAddress(std::string newAddress); }; 39
  • 40. Defining the copy constructor why const? object that you are copying from MITPerson::MITPerson(const MITPerson& other){ name = other.name; id = other.id; address = other.address; } 40
  • 41. Default copy constructor �automatically generated by the compiler �copies all non-static members (primitives & objects) �invokes the copy constructor of member objects MITPerson::MITPerson(const MITPerson& other){ name = other.name; id = other.id; address = other.address; } 41
  • 42. Assigning an object to another MITPerson p1(921172, “James Lee”, “32 Vassar St.”); MITPerson p2(978123, “Alice Smith”, “121 Ames St.”); p2 = p1; // assigns p2 to p1, does NOT create a new object So how do objects get assigned to each other? Copy assignment operator is called. Object& Object::operator=(const Object& other) { ... } 42
  • 43. Copy assignment operator in MITPerson #include <string> class MITPerson { protected: int id; std::string name; std::string address; public: MITPerson(int id, std::string name, std::string address); MITPerson(const MITPerson& other); MITPerson& operator=(const MITPerson& other); void displayProfile(); void changeAddress(std::string newAddress); }; 43
  • 44. Defining the copy assignment operator MITPerson& MITPerson::operator=(const MITPerson& other){ name = other.name; id = other.id; address = other.address; return *this; // returns a newly assigned MITPerson } MITPerson p1(921172, “James Lee”, “32 Vassar St.”); MITPerson p2(978123, “Alice Smith”, “121 Ames St.”); p2 = p1; 44
  • 45. Defining the copy assignment operator MITPerson& MITPerson::operator=(const MITPerson& other){ name = other.name; id = other.id; address = other.address; return *this; } Again, if you don’t define one, the compiler will automatically generate a copy assignment operator So why do we ever need to define copy constructors & copy assignment operators ourselves? 45
  • 46. Default copy constructor - caution! class B { public: void print() { std::cout << "Hello World!n”; } }; class A { B* pb; int x; public: A(int y) : x (y) { pb = new B(); } ~A() { delete pb; } // destructor void printB() { pb->print(); } }; void foo(A a) { a.printB(); } int main() { A a1(5); a1.printB(); foo(a1); return 0; } 46
  • 47. Default copy constructor - caution! class B { public: void print() { std::cout << "Hello World!n”; } }; class A { B* pb; int x; public: A(int y) : x (y) { pb = new B(); } ~A() { delete pb; } // destructor Double free! }; void printB() { pb->print(); } How do we fix this? void foo(A a) { a.printB(); } int main() { A a1(5); a1.printB(); foo(a1); return 0; } 47
  • 48. Default copy constructor - caution! class B { public: void print() { std::cout << "Hello World!n”; } }; class A { B* pb; int x; public: A(int y) : x (y) { pb = new B(); } A(const A& other) { // copy constructor x = other.x; pb = new B(); } ~A() { delete pb; } // destructor A& operator=(const A& other) { // copy assignment operator x = other.x; delete pb; // clean up the junk in the existing object! pb = new B(); return *this; } void printB() { pb->print(); } }; 48
  • 49. Rule of three in C++ If you define any one of the three in a class, then you should define all three (you will probably need them!) �destructor �copy constructor �copy assignment operator 49
  • 51. Binary search algorithm int binarySearch(int a[], int key, int length) { int low = 0; int high = length - 1; while (low <= high) { int mid = (low + high) / 2; int midVal = a[mid]; if (midVal < key) low = mid + 1 else if (midVal > key) high = mid - 1; else return mid; // key found } return -(low + 1); // key not found } Courtesy of Joshua Bloch. Used with permission. based on from Joshua Bloch’s implementation in java.util 51
  • 52. Binary search bug int binarySearch(int a[], int key, int length) { int low = 0; int high = length - 1; while (low <= high) { int mid = (low + high) / 2; int midVal = a[mid]; if (midVal < key) low = mid + 1 Can you find the bug? else if (midVal > key) high = mid - 1; else return mid; // key found } return -(low + 1); // key not found Courtesy of Joshua Bloch. Used with permission. } 52
  • 53. Binary search bug int binarySearch(int a[], int key, int length) { int low = 0; int high = length - 1; while (low <= high) { int mid = (low + high) / 2; int midVal = a[mid]; if (low + high) > MAX_INTEGER, it will overflow! if (midVal < key) low = mid + 1 dangerous array access! else if (midVal > key) (Java will at least throw high = mid - 1; else an exception) return mid; // key found } return -(low + 1); // key not found Courtesy of Joshua Bloch. Used with permission. } 53
  • 54. One solution Instead of: int mid = (low + high) / 2; use: int mid = low + (high - low) / 2; Surprisingly, most implementations of the binary search tree had this bug! (including java.util) http://googleresearch.blogspot.com/2006/06/extra­ extra-read-all-about-it-nearly.html 54
  • 56. Useful links Google C++ style guideline http://google-styleguide.googlecode.com/svn/trunk/ cppguide.xml C++ FAQ http://www.parashift.com/c++-faq-lite/index.html 56
  • 57. There are many things we haven’t told you! Thinking in C++ (B. Eckel) Free online edition! Essential C++ (S. Lippman) Effective C++ (S. Meyers) C++ Programming Language (B. Stroustrup) Design Patterns (Gamma, Helm, Johnson,Vlissides) Object-Oriented Analysis and Design with Applications (G. Booch, et. al) 57
  • 58. Congratulations! Now you know enough about C/C++ to embark on your own journey! 58
  • 59. MIT OpenCourseWare http://ocw.mit.edu 6.088 Introduction to C Memory Management and C++ Object-Oriented Programming January IAP 2010 For information about citing these materials or our Terms of Use, visit: http://ocw.mit.edu/terms.