55
COMS W3101: Programming Languages (C++) Instructor: Austin Reiter Lecture 3

COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

  • Upload
    others

  • View
    5

  • Download
    0

Embed Size (px)

Citation preview

Page 1: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

COMS W3101: Programming Languages (C++)

Instructor: Austin Reiter

Lecture 3

Page 2: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

Last Time

• Storage Class/Scope/Linkage

• Intro to Objects

• Classes

• Constructors

• Header/Source File Layout

• const

• Pointer arithmetic

Page 3: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

Outline For Today

• std::string

• Deeper look at classes

• Inheritance

Page 4: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

String Processing

• Can use an array of characters as a string – Remember the terminating null character

• Can also use std::string from the C++ standard library

• A single character is represented by single quotes: ‘c’

• A string is represented by double quotes: “John Doe”

• We can use std::cin to read in a word: char word[20]; std::cout << “Enter your word: “; std::cin >> setw(20) >> word;

Specifies that cin should read a maximum of 19 characters into the array word

Page 5: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

String Processing

• We can also get an entire line of text – The getline() function reads a line of text from the stream

and stops reading characters when the delimiter character ‘\n’ is reached char sentence[80]; cin.getline(sentence, 80, „\n‟);

– It’s important to note that if a sentence (w/ white spaces) is written, we can’t write: std::cin >> sentence;

Because cin will go until the first white space and stop. The getline() function reads an entire line until the „\n‟ character is encountered.

Page 6: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

String Manipulation Function Prototype #include<cstring>

Function Description

char* strcpy(char* s1, const char* s2) Copies the string s2 into s1. Return s1.

char* strncpy(char* s1, const char* s2, size_t n)

Copies at most n characters of the string s2 into s1. Return s1.

char* strcat(char* s1, const char* s2) Append the string s2 to s1. The first character of s2 overwrites terminating null character of s1. Return s1.

char* strncat(char* s1, const char* s2, size_t n)

Appends at most n characters of the string s2 to s1. The first character of s2 overwrites terminating null character of s1. Return s1.

int strcmp(const char* s1, const char* s2) Compares s1 with s2. Return 0 if they’re equal; return <0 if s1 < s2; return >0 if s1 > s2.

int strncmp(const char* s1, const char* s2, size_t n)

Compares up to n characters of s1 with s2. Return 0 if they’re equal; return <0 if s1 < s2; return >0 if s1 > s2.

size_t strlen(const char* s) Return the length of the string s preceding the terminating null character.

Page 7: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

std::string

• A special type of container meant to deal with sequences of characters (it’s a class!)

• Contains many built-in useful operations • Can construct with empty strings or character arrays

– Copy constructor & assignment operator overloaded to take std::string as well as char arrays

• Can dynamically resize length of string – More on Standard Template Library (STL) later on

• Can access individual characters with [] operator • Can combine strings with +, += operators • Can compare strings with == operator • Very intuitive to use • Can access raw data with c_str() function

– This returns a const char* pointer

• Let’s look at a full list of the functions: http://www.cplusplus.com/reference/string/string/

Page 8: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

std::string

• As before, we can read a sentence into a string, but this time without specifying the number of characters of the string (unlike the character array): std::string sentence; getline(std::cin, sentence); This will read in spaces as well, until the first „\n‟ is found. All allocations happen automatically inside the class definitions for std::string.

Page 9: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

Deeper Look at Classes

• More on const

• friend

• this pointer

• static

• Information Hiding

• Data Abstraction

• Inheritance

• Polymorphism (Next Lecture)

Page 10: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

Class Members

• We talked about the length of life of different types of variables: – Local (stack) variables: die when the next closing } is reached – Global variables: live for the entirety of the program, and is

accessible everywhere. – Dynamically-allocated variables: the memory lives for the

entirety of the program once new is called, or until delete is called. But is only accessible in the scope of where it was created (unless you pass it around via pointer memory addresses, right?).

• So what about member variables? – The scope is the class itself. What does that mean? – Homework question

Page 11: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

Constant Objects

• The principle of least privilege

• Some objects need to be modified and some do not

• The const keyword says an object is not modifiable and any attempt will result in a compiler error

• This means initialization is essential!

Page 12: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

Constant Class Methods

• Class methods may or may not modify class members (i.e., change the state of the object) – Those that don’t (or shouldn’t) change the state should be declared const

• C++ disallows member function calls for const objects unless that member function is also declared as const

class Widget

{

public:

Widget();

~Widget();

int getValue();

};

const Widget myWidget;

int value = myWidget.getValue(); ERROR!

Page 13: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

Constant Class Methods

• Class methods may or may not modify class members (i.e., change the state of the object) – Those that don’t (or shouldn’t) change the state should be declared const

• C++ disallows member function calls for const objects unless that member function is also declared as const

class Widget

{

public:

Widget();

~Widget();

int getValue() const;

};

const Widget myWidget;

int value = myWidget.getValue(); CORRECT!

Page 14: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

Constant Class Methods

• Class methods may or may not modify class members (i.e., change the state of the object) – Those that don’t (or shouldn’t) change the state should be declared const

– This signals the user that this function is “safe”

• C++ disallows member function calls for const objects unless that member function is also declared as const – Also, you can’t call a non-const method from a const method

when the object is const (i.e., can’t trick the compiler)

• Constructors are the exception: they do not need to be const in order to construct a const object. – They can call non-const methods during construction of a const

object. – The “constness” of an object is enforced right after the constructor

completes initialization

Page 15: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

Constant Class Members

• Members of a class may be constant – However it must be initialized correctly, in the

member initializer class Increment { public: Increment(int c = 0, int i = 1); void addIncrement() { count += increment; } private: int count; const int increment; };

Increment::Increment(int c, int i)

{

count = c;

increment = i;

}

ERROR: cannot modify a const object. DIFFERENCE B/W CONSTRUCTION AND ASSIGNMENT!

Page 16: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

Constant Class Members

• Members of a class may be constant – However it must be initialized correctly, in the

member initializer class Increment { public: Increment(int c = 0, int i = 1); void addIncrement() { count += increment; } private: int count; const int increment; };

Increment::Increment(int c, int i)

: count(c), increment(i)

{

}

OK: this is the correct way to initialize your constant member object

Page 17: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

Member Initializer

• What else needs to be constructed in the member initializer?

• Classes may contain objects from other classes

• Recall that every object has a constructor class AlarmClock { public: AlarmClock(); ~AlarmClock(); private: Time timer; };

AlarmClock::AlarmClock()

{

// If you do nothing, by default

// Time‟s default constructor is

// called on timer when this

// AlarmClock constructor is called.

}

This can be a problem if (for some reason) the default constructor is private.

Page 18: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

Member Initializer

• What else needs to be constructed in the member initializer?

• Classes may contain objects from other classes

• Recall that every object has a constructor class AlarmClock { public: AlarmClock(); ~AlarmClock(); private: Time timer; };

AlarmClock::AlarmClock()

: timer(0,0,0)

{

// However, if timer needs a

// non-default constructor, it

// must be called in the member

// initializer.

}

Page 19: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

Member Initializer

• What else needs to be constructed in the member initializer?

• Classes may contain objects from other classes

• Recall that every object has a constructor class AlarmClock { public: AlarmClock(); ~AlarmClock(); private: Time* timer1; Time* timer2; };

AlarmClock::AlarmClock()

: timer1(new Timer(0,0,0))

{

// Unless the member is a pointer.

// Then you can do it either way,

// although the member initializer

// is better whenever possible.

// (note: difference b/w construction

// and assignment)

timer2 = new Timer();

}

Page 20: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

friend functions and Classes

• A friend function of a class is defined outside that class’s scope

– However, the keyword friend gives the right to access the public and non-public members of the class

• Standalone functions or entire classes may be declared to be friends of another class

• Often used with operator overloading

– Consider arithmetic operators of Matrix classes (homework #3!)

Page 21: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

friend functions and Classes

Class Count

{

friend void setX(Count& c, int val); // friend declaration

public:

Count() : x(0)

{

}

private:

int x; // private data member

};

// Function setX can modify private members of class Count because it is

// declared as a friend of Count.

void setX(Count& c, int val)

{

c.x = val; // allowed b/c setX is a friend of Count

}

Let’s note 2 things here: - by default, with no access specifier label, everything is private in a class

Page 22: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

friend functions and Classes

Class Count

{

friend void setX(Count& c, int val); // friend declaration

public:

Count() : x(0)

{

}

private:

int x; // private data member

};

// Function setX can modify private members of class Count because it is

// declared as a friend of Count.

void setX(Count& c, int val)

{

c.x = val; // allowed b/c setX is a friend of Count

}

Let’s note 2 things here: - by default, with no access specifier label, everything is private in a class - even though appears in class definition of Count, friends

are not member functions (standalone function) - Notions of private, public, protected are

irrelevant for friends, so put them anywhere in the class definition.

Page 23: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

Using The this Pointer

• Every object has access to its own address through a pointer called this (a C++ keyword)

• It is not part of the object itself • It is simply passed by the compiler as an implicit argument

to each of the member’s non-static member functions • For example, inside a:

– Non-constant member function of class Employee, the this pointer implicitly has type Employee* const • Recall the rules of const with pointers: this is a constant pointer to a

non-constant Employee object, b/c this can’t point anywhere else!

– Constant member function of class Employee, the this pointer implicitly has type const Employee* const • A constant pointer to a constant Employee object

Page 24: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

Using The this Pointer

• Common in assignment operator overloading class Widget { public: Widget(); ~Widget(); Widget& operator=(const Widget& rhs) { // Copy data FROM rhs TO my members x = rhs.x; data = rhs.data; // Now return a reference to ME—this allows for // cascaded function calls: // // ex: // a = b = c = d; // return *this; // de-reference the this pointer } private: int x; double* data; };

Page 25: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

Using The this Pointer

• So what does it mean? • We can think of it like this:

– When we call member functions from other member functions, we simply call the function as usual, without any object (meaning no “.” or “->” operators.

– When we call member functions outside the class, we use the object name followed by a “.” (or “->” if it’s a pointer): Widget w; w.doSomething();

Page 26: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

Using The this Pointer

• Alternatively: void Widget::doSomething()

{

}

void Widget::doSomethingElse()

{

// Just like calling through the object, keeping

// the state (i.e., it‟s not a copy)

this->doSomething();

}

Page 27: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

Assignment Chains

• Most commonly used with overloading the assignment operator • C++ allows cascading chains of assignments that are right-

associative: int x,y,z; x = y = z = 15; (underneath the hood, looks like this: x = (y = (z = 15));

• The reason this works is that the assignment returns a reference (&) to the left-hand argument.

• This is why we use *this while returning a reference to “me” in the overloaded assignment definition! – In fact, we do this with all assignment operator overloading: +=, -=, etc…

Page 28: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

Using The this Pointer

• Because it’s a pointer, you can identify “self-assignments”. This can be dangerous in the following example: class Widget { … private: Bitmap *pb; // ptr to heap allocated object }; Widget& Widget::operator=(const Widget& rhs) // unsafe assignment { delete pb; // stop using current bitmap pb = new Bitmap(*rhs.pb); // start using a copy of rhs‟s bitmap return *this; } WHY??

Page 29: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

Using The this Pointer

• Because it’s a pointer, you can identify “self-assignments”. This can be dangerous in the following example: class Widget { … private: Bitmap *pb; // ptr to heap allocated object }; Widget& Widget::operator=(const Widget& rhs) // unsafe assignment { delete pb; // stop using current bitmap pb = new Bitmap(*rhs.pb); // start using a copy of rhs‟s bitmap return *this; } What if *this and rhs point to the same thing? Then delete destroys the data for both. If so, after the assignment, we will be pointing to a deleted object!

Page 30: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

Using The this Pointer

• Because it’s a pointer, you can identify “self-assignments”. This can be dangerous in the following example: class Widget { … private: Bitmap *pb; // ptr to heap allocated object }; Widget& Widget::operator=(const Widget& rhs) { // Identify self-assignment. If so, do nothing; if (this == &rhs) return *this; delete pb; // stop using current bitmap pb = new Bitmap(*rhs.pb); // start using a copy of rhs‟s bitmap return *this; } this is a pointer

to “me” &rhs is a pointer to the right-hand side of the assignment

Page 31: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

static Class Members

• Up until now, we believe that each instance object of a class has its own copy of all the data members of the class

– Example

• Sometimes we want only one copy of a variable to be shared by all instances of a class

– A static data member represents “class-wide” information

Page 32: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

static Class Members

• Example: we have an application that uses custom Array classes of known sizes, but we want to extend the functionality of standard C++ arrays – We want to allow objects of Arrays of size 128 and 512

class Array128 { public static const int SizeOfArray = 128; Array128(); ~Array128(); private: float data[SizeOfArray]; }; class Array512 { public static const int SizeOfArray = 512; Array512(); ~Array512(); private: float data[SizeOfArray]; };

Page 33: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

static Class Members

• Example: global count of number of times my class is instantiated, anywhere

• See code example (Employee)

Page 34: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

Data Abstraction and Information Hiding

• A user of my class doesn’t need to know about my implementations

• A user only needs to know what functionality my class offers, and this is referred to as data abstraction.

• Among other reasons, this allows a particular class to be replaced with another version without affecting the rest of the code – This is only true as long as the public services of the

class do not change (same prototypes)

Page 35: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

Data Abstraction and Information Hiding

• Primary activities of object-oriented programming in C++ are the creation of types (i.e., classes) and interactions between them

• Abstract Data Types (ADTs) – Consider the int data type. Most associate this with an integer in mathematics. Rather, it is

an abstract representation of an integer. • They are fixed in size, unlike in mathematics • Value must fit within 32-bits of data, or we get overflow problems

– Consider the char data type. These are normally 8-bit patterns of 1’s and 0’s, and they look nothing like the characters they represent. • Can’t necessarily represent any possible character in any possible language • Again, only an approximation of what it represents

• These are ways of representing real-world notions to some satisfactory level of precision within a computer

• These are important concepts to consider when creating customized objects – What are you trying to represent? – What are the limitations? – What are the behaviors? – …

Page 36: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

Inheritance

• New classes created (derived) from previous classes (base classes)

• The derived class has all the features of the base class plus additional new features specific to that derived class

• Features of Inheritance: – Reusability: once a base class is defined and compiled,

it doesn’t need to be reworked again. • Just add new features as needed

– Saves time and effort

Page 37: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

Inheritance

• Base Classes and Derived Classes • “Is-a” versus “Has-a”

– Ex: (is-a) a rectangle is a quadrilateral. Therefore, the Rectangle class inherits from the Quadrilateral class. • The quadrilateral is the base class and the rectangle is the derived

class.

– Ex: (has-a) Classes have members that are objects of other classes • An AlarmClock class has a Timer class.

• Objects of all classes derived from a common base class can be treated as objects of that class – THIS IS A KEY CONCEPT!

Page 38: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

Inheritance Hierarchy - Shapes

Shape

TwoDShape ThreeDShape

Circle Square Triangle Sphere Cube Tetrahedron

Page 39: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

Inheritance Hierarchy - Shapes

• Begin with base class Shape • Classes TwoDShape and ThreeDShape derive

from base class Shape • Then we have specific 2D-shapes and specific 3D-

shapes • Follow the hierarchy to determine relationships:

– Ex: a Triangle is-a TwoDShape and is-a Shape.

• To specify that class TwoDShape is derived from (or inherits from) class Shape, we do as follows: class TwoDShape : public Shape

public inheritance

Page 40: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

Inheritance Access

• There are 3 types of inheritance – Public

– Protected (rarely used)

– Private (very rarely used)

• With all forms of inheritance, private members of a base class are not accessible directly from that class’s derived class, but these private members are still inherited – i.e., they are still considered parts of the derived

classes

Page 41: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

Inheritance Access

• public – All other base members retain their original member

access when they become members of the derived class (i.e., base public members are derived public members, etc).

– A derived class with public inheritance, you inherit all members of the base class but the constructor. Each class has its own specific constructor. • C++ requires a derived class constructor to call its base class

constructor to initialize the base class data members.

– Derived classes cannot access private members of the base class. Using setters/getters that are public in the base class accomplishes this.

– friend functions are not inherited

Page 42: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

Inheritance Access

• Recall protected members • Provides intermediate access between public and private

• Can be accessed by: – The base class which declares it – friend of the base class which declares it – Members and friends of any class derived from that base class

• Making the data members of a base class protected makes accessing them slightly more efficient as we can avoid the overhead involved in using setters/getters to access them. But this can be dangerous since you can now change values that the base class may depend on in an implementation being inherited.

• Using private is still better software engineering practice!

Page 43: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

Inheritance Access

• If instead of deriving as public, we derive as protected, the difference becomes: – All public and protected members of the base

class become protected members of the derived class.

• If we derived as private: – All public and protected members of the base

class become private members of the derived class (i.e., the functions become utility functions).

• Neither protected or private inheritance relationships are considered is-a relationships.

Page 44: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

Redefining Base Class Methods

• When a derived class member function redefines a base class member function, the base class member can be accessed from the derived class by preceding the base class member name with the base class name and the binary scope resolution operator (::)

Page 45: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

Constructors/Destructors in Derived Classes

• Instantiating a derived class begins a chain of constructor calls – Before performing its own tasks, the derived class

calls the base class’s constructor, and so on down the chain until the top of the hierarchy.

– The derived class constructor gets called last

• When a derived class is destroyed: – A chain of destructors is called, but in reverse. First

the derived class destructor is called, then the base class’s destructor, and so on up the hierarchy.

Page 46: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

virtual Function

• Keyword which specifies that the function may be overridden by a derived class by a function with the same signature.

• More of a polymorphism concept, but it comes up with inheritance programming.

• Any function you which has behaviors specific to each individual derived class should be declared virtual. – Purely virtual requires a redefinition in derived

classes. • Show example of purely virtual method

Page 47: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

Inheritance Example

• See Shape/Rectangle code example

– Notice virtual vs. non-virtual callMe() method overriding! Never redefine an inherited non-virtual function!

Page 48: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

Inheritance – To Think About

• Make sure your public inheritance model “is-a”

class Person {…};

class Student : public Person {…};

Every student is a person, but not every person is a student. This is the correct hierarchy for this relationship. Otherwise we get into bad circular logic!

Page 49: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

Inheritance – To Think About

• But be careful. For example, it is a fact that a penguin is a bird, and it is a fact that birds can fly. So what if we do this: class Bird { public: virtual void fly(); // birds can fly … }; class Penguin : public Bird // penguins are birds { … };

So what’s the problem? How can we avoid basic issues of the English language?

Page 50: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

Inheritance – To Think About

• Come up with a better hierarchy! class Bird { … // no fly function is declared }; class FlyingBird : public Bird { public: virtual void fly(); … }; class Penguin : public Bird { … // no fly function is declared };

This works. Any other ideas??

Page 51: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

Inheritance – To Think About

• Runtime error catching class Bird { public: virtual void fly(); // birds can fly … }; class Penguin : public Bird // penguins are birds { public: virtual void fly() { error(“Attempt to make a penguin fly!”); } };

This works too! It’s all about design, and there are different ways to approach the problem if you think first, code second.

Page 52: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

Inheritance – To Think About

• This is the wonderful world of public inheritance.

• It makes you rethink the instincts you’ve learned in other fields of study

• EVERYTHING that applies to a base class MUST ALSO apply to the derived class.

• A square is definitely a rectangle, but some things you do to a rectangle you can’t do to a square

– Ex: make a rectangle bigger in one dimension

Page 53: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

Dynamic Types

// A class for geometric shapes

class Shape

{

public:

enum ShapeColor { Red, Green, Blue };

virtual void draw(ShapeColor = Red) const = 0;

};

class Rectangle : public Shape

{

public:

virtual void draw(ShapeColor = Green) const;

};

class Circle : public Shape

{

public:

virtual void draw(ShapeColor color) const;

};

Shape* ps;

Shape* pc = new Circle;

Shape* pr = new Rectangle;

Dynamic type is determined by the type of the object to which it currently refers (i.e., how will it actually behave?). pc’s dynamic type is Circle* pr’s dynamic type is Rectangle* ps does not yet have a dynamic type (it points to nothing)

Page 54: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

Dynamic Types

// A class for geometric shapes

class Shape

{

public:

enum ShapeColor { Red, Green, Blue };

virtual void draw(ShapeColor = Red) const = 0;

};

class Rectangle : public Shape

{

public:

virtual void draw(ShapeColor = Green) const;

};

class Circle : public Shape

{

public:

virtual void draw(ShapeColor color) const;

};

Shape* ps;

Shape* pc = new Circle;

Shape* pr = new Rectangle;

Virtual functions are dynamically-bound, however, the default parameters are statically-bound. The code example from before shows virtual vs non-virtual dynamic binding. In this case, you may end up invoking a virtual function in a derived class but getting a default parameter from a base class – WEIRD!

Page 55: COMS W3101: Programming Languages (C++)areiter/CS_Webpage/COMS3101_Sp11_1_files/COMS31… · pointer called this (a C++ keyword) •It is not part of the object itself •It is simply

Multiple Inheritance

• We can inherit from multiple classes at the same time • Must be careful for ambiguities!

class A { public: virtual void callMe(); … }; class B { public: virtual void callMe(); … }; class C : public A, public B { public: … }; C obj; obj.callMe(); // this is ambiguous! Should I use A‟s or B‟s callMe() method?