0% found this document useful (0 votes)
72 views24 pages

CSCI 104 Inheritance: Mark Redekopp David Kempe

The document discusses constructor initialization lists in C++. It explains that constructor initialization lists allow data members to be initialized by calling their constructors before the body of the constructor is executed. This avoids unnecessary assignments in the constructor body and is more efficient. The document provides examples of using initialization lists to initialize base class members from derived class constructors.

Uploaded by

Rahul Kumar
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
72 views24 pages

CSCI 104 Inheritance: Mark Redekopp David Kempe

The document discusses constructor initialization lists in C++. It explains that constructor initialization lists allow data members to be initialized by calling their constructors before the body of the constructor is executed. This avoids unnecessary assignments in the constructor body and is more efficient. The document provides examples of using initialization lists to initialize base class members from derived class constructors.

Uploaded by

Rahul Kumar
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 24

1

CSCI 104
Inheritance
Mark Redekopp
David Kempe
2

Files for Today


• $ mkdir inh
• $ cd inh
• $ wget http://ee.usc.edu/~redekopp/cs104/inh.tar
• $ tar xvf inh.tar
• $ make
3

Constructor Initialization Lists


class Person{
public:
Person();
Person(string myname);
Person(string myname, int myid);
string get_name() { return name; }
void add_grade(int score);
int get_grade(int index);
private:
string name_;
int id_;
};
Person::Person() { }
Person::Person(string myname) string name_
{ name_ = myname;
int id_
id_ = -1;
}
Person::Person(string myname, int myid)
{ name_ = myname;
id_ = myid;
}
...

• C++ constructors often have a bunch of assignments and initializations to the


data members.
4

Constructor Initialization Lists


Person::Person() /* mem allocated here */ Person::Person(string myname) :
{ name(myname), id(12313)
name("Tommy Trojan"); { }
id = 12313;
}

You can't call member You would have to call the member
constructors in the {…} constructors in the initialization list context

• Rather than writing many assignment statements


we can use a special initialization list technique
for C++ constructors
– Constructor(param_list) : member1(param/val), …, memberN(param/val)
{…}

• We are really calling the respective constructors


for each data member
5

Constructor Initialization Lists


Person::Person() Person::Person() :
{ name(), id()
name = "Tommy Trojan"; // calls to default constructors
id = 12313 {
} name = "Tommy Trojan";
id = 12313
}

You can still assign data But any member not in the initialization list will
members in the {…} have its default constructor invoked before the
{…}

• You can still assign values in the constructor but


realize that the default constructors will have
been called already
• So generally if you know what value you want to
assign a data member it's good practice to do it
in the initialization list
6

Constructor Initialization Lists


Person::Person() { }
Person::Person(string myname) Memory is
string name_
{ name_ = myname;
id_ = -1;
allocated
int id_
} before the '{' …
Person::Person(string myname, int myid)
{ name_ = myname;
id_ = myid;
…then values
} name_ = myname
... copied in when
id_ = myid assignment
String Operator=() Called
performed
Initialization using
assignment
Person::Person() { } Memory is
Person::Person(string myname) : name_ = myname
allocated and
name_(myname), id_(-1) id_ = myid filled in "one-
{ }
Person::Person(string myname, int myid) : step"
name_(myname), id_(myid)
{ }
...

String Copy Constructor


Called

Initialization List
approach
7

INHERITANCE
8

Object Oriented Design


• Encapsulation
– Combine data and operations on that data into a
single unit (e.g. a class w/ public and private
aspects)
• Inheritance
– Creating new objects (classes) from existing ones
• Polymorphism
– Using the same expression to denote different
operations
9

Inheritance
• A way of defining interfaces, re-using classes and
extending original functionality
• Allows a new class to inherit all the data members and
member functions from a previously defined class
• Works from more general
objects to more specific objects
– Defines an “is-a” relationship
– Square is-a rectangle is-a shape
– Square inherits from Rectangle which base
inherits from Shape child

– Similar to classification of organisms: grandchild

• Animal -> Vertebrate -> Mammals -> Primates


10

Base and Derived Classes


• Derived classes inherit
class Person {
public:
Person(string n, int ident);

all data members and string get_name();


int get_id();
private:
functions of base class };
string name_; int id_;

class Student : public Person {

• Student class inherits: public:


Student(string n, int ident, int mjr);
int get_major();
– get_name() and get_id() double get_gpa();
void set_gpa(double new_gpa);

– name_ and id_ member private:


int major_; double gpa_;
};
variables
Class Person Class Student
string name_ string name_

int id_ int id_

int major_

double gpa_
11

Base and Derived Classes


• Derived classes inherit class Person {
public:
Person(string n, int ident);
all data members and string get_name();
int get_id();
private:
functions of base class };
string name_; int id_;

class Student : public Person {


• Student class inherits: public:
Student(string n, int ident, int mjr);
int get_major();
– get_name() and get_id() double get_gpa();
void set_gpa(double new_gpa);
– name_ and id_ member private:
int major_; double gpa_;
variables };

int main()
Class Person Class Student {
Student s1("Tommy", 1, 9);
string name_ string name_ // Student has Person functionality
// as if it was written as part of
int id_ int id_
// Student
int major_ cout << s1.get_name() << endl;

double gpa_ }
12

Inheritance Example Inheritance Diagrams


Component (arrows shown base
to derived class
• Component relationships)

– Draw()
Window ListBox
– onClick()
• Window
– Minimize()
– Maximize() ScrollBox DropDown
Box
• ListBox
– Get_Selection()

• ScrollBox
– onScroll()
• DropDownBox
– onDropDown()
13

Constructors and Inheritance


class Person {
• How do we initialize base public:
Person(string n, int ident);
class data members? ...
private:
• Can't assign base class string name_;
int id_;
members if they are };
class Student : public Person {
private public:
Student(string n, int ident, int mjr);
...
private:
int major_;
double gpa_;
};
Student::Student(string n, int ident, int mjr)
{
name_ = n; // can't access name_ in Student
id_ = ident;
major_ = mjr;
}
14

Constructors and Inheritance


• Constructors are only called when class Person {
a variable ‘enters scope’ (i.e. is public:
Person(string n, int ident);
created) and cannot be called ...
private:
directly string name_;
int id_;
– How to deal with base };
constructors? class Student : public Person {
public:
• Also want/need base class or Student(string n, int ident, int mjr);
...
other members to be initialized private:
before we perform this object's int major_;
double gpa_;
constructor code };

• Use initializer format instead Student::Student(string n, int ident, int mjr)


{
– See example below // How to initialize Base class members?
Person(n, ident); // No! can’t call Construc.
// as a function
}

Student::Student(string n, int ident, int mjr) : Person(n, ident)


{
cout << "Constructing student: " << name_ << endl;
major_ = mjr; gpa_ = 0.0;
}
15

Constructors & Destructors


• Constructors
– A Derived class will automatically call its Base class
constructor BEFORE it's own constructor executes,
either: base
• Explicitly calling a specified base class constructor in the child
initialization list grandchild
• Implicitly calling the default base class constructor if no
base class constructor is called in the initialization list Constructor call ordering
• Destructors
– The derived class will call the Base class destructor
automatically AFTER it's own destructor executes
• General idea
– Constructors get called from base->derived (smaller to
base
larger)
child
– Destructors get called from derived->base (larger to
smaller) grandchild

Destructor call ordering


16

Constructor & Destructor Ordering


class A { int main()
int a; {
public: cout << "Allocating a B object" << endl;
A() { a=0; cout << "A:" << a << endl; } B b1;
~A() { cout << "~A" << endl; } cout << "Allocating 1st C object" << endl;
A(int mya) { a = mya; C* c1 = new C;
cout << "A:" << a << endl; } cout << "Allocating 2nd C object" << endl;
}; C c2(4,5);
cout << "Deleting c1 object" << endl;
class B : public A { delete c1;
int b; cout << "Quitting" << endl;
public: return 0;
B() { b = 0; cout << "B:" << b << endl; } } Test Program
~B() { cout << "~B "; }
B(int myb) { b = myb; Allocating a B object
cout << "B:" << b << endl; } A:0
}; B:0
Allocating 1st C object
class C : public B { A:0
int c; B:0
public: C:0
C() { c = 0; cout << "C:" << c << endl; } Allocating 2nd C object
~C() { cout << "~C "; } A:0
C(int myb, int myc) : B(myb) { B:4
c = myc; C:5
cout << "C:" << c << endl; } Deleting c1 object
}; ~C ~B ~A
Quitting
Sample Classes ~C ~B ~A
~B ~A Output
17

Protected Members
• Private members of a base class Person {
public:
class can not be accessed ...
private:
directly by a derived class };
string name_; int id_;

member function class Student : public Person {


public:
– Code for print_grade_report() void print_grade_report();
would not compile since ‘name_’ is private:
int major_; double gpa_;
private to class Person };

• Base class can declare void Student::print_grade_report()


{
variables with protected }
cout << “Student “ << name_ << ... X
storage class
– Private to anyone not inheriting
class Person {
from the base public:
– Derived classes can access directly ...
protected:
string name_; int id_;
};
18

Public/Private/Protected Access
class Person {
• Derived class sees base class members public:
using the base class' specification Person(string n, int ident);
string get_name();
– If Base class said it was public or protected, int get_id();
the derived class can access it directly private: // INACCESSIBLE TO DERIVED
string name_; int id_;
– If Base class said it was private, the derived };
class cannot access it directly
Base Class
• public/private identifier before base
class Student : public Person {
class indicates HOW the public base public:
Student(string n, int ident, int mjr);
class members are viewed by clients int get_major();
(those outside) of the derived class double get_gpa();
void set_gpa(double new_gpa);
– public => public base class members are private:
int major_; double gpa_;
public to clients (others can access) };
– private => public & protected base class class Faculty : private Person {
public:
members are private to clients (not Faculty(string n, int ident, bool tnr);
accessible to the outside world) bool get_tenure();
private:
bool tenure_;
};

Derived Classes
19

Inheritance Access Summary


class Person {
public:
• Base class Person(string n, int ident);
string get_name();
– Declare as protected if you want to int get_id();
allow a member to be directly private: // INACCESSIBLE TO DERIVED
accessed/modified by derived classes string name_; int id_;
};
Base Class
• Derive as public if… class Student : public Person {
– You want users of your derived class to be public:
able to call base class functions/methods Student(string n, int ident, int mjr);
int get_major();
• Derive as private if… double get_gpa();
– You only want your internal workings to call void set_gpa(double new_gpa);
private:
base class functions/methods int major_; double gpa_;
};
class Faculty : private Person {
Inherited Public Protected Private public:
Base Faculty(string n, int ident, bool tnr);
bool get_tenure();
Public Public Protected Private private:
bool tenure_;
Protected Protected Protected Private };

Private Private Private Private int main(){


Student s1("Tommy", 73412, 1);
External client access to Base class members Faculty f1("Mark", 53201, 2);
is always the more restrictive of either the base cout << s1.get_name() << endl; // works
cout << f1.get_name() << endl; // fails
declaration or inheritance level }
20

When to Inherit Privately


class List{
public:
• Suppose I want to create a FIFO (First- List();
void insert(int loc, const int& val);
in, First-Out) data structure where you int size();
can only int& get(int loc);
void pop(int loc;)
– Push in the back private:
IntItem* _head;
– Pop from the front };

• FIFO is-a special List


Base Class
• Do I want to inherit publicly from List
class FIFO : public List // or private List
• NO!!! Because now the outside user { public:
FIFO();
can call the base List functions and push_back(const int& val)
break my FIFO order { insert(size(), val); }
int& front();
• Inherit privately to hide the base class { return get(0); }
void pop_front();
public function and make users go { pop(0); }
};
through the derived class' interface
– Private inheritance defines an "as-a" Derived Class
relationship
FIFO f1;
f1.push_back(7); f1.push_back(8);
f1.insert(0,9)
21

Overloading Base Functions


class Car{
public:
• A derived class may want to double compute_mpg(); Class Car
private:
redefined the behavior of a string make; string model;
string make

member function of the }; string model

base class double Car::compute_mpg()


{
• A base member function can if(speed > 55) return 30.0;
else return 20.0;
be overloaded in the derived }
class
class Hybrid : public Car {
• When derived objects call public: Class Hybrid
that function the derived void drive_w_battery();
double compute_mpg();
string make
version will be executed private: string model
string batteryType;
• When a base objects call }; string battery

that function the base double Hybrid::compute_mpg()


{
version will be executed if(speed <= 15) return 45; // hybrid mode
else if(speed > 55) return 30.0;
else return 20.0;
}
22

Scoping Base Functions


class Car{
public:
• We can still call the base function double compute_mpg();
private:
version by using the scope operator string make; string model;
(::) };
– base_class_name::function_name()
class Hybrid : public Car {
public:
double compute_mpg();
private:
string batteryType;
};
double Car::compute_mpg()
{
if(speed > 55) return 30.0;
else return 20.0;
}

double Hybrid::compute_mpg()
{
if(speed <= 15) return 45; // hybrid mode
else return Car::compute_mpg();
}
23

Inheritance vs. Composition


• Software engineers debate about class Car{
public:
using inheritance (is-a) vs. double compute_mpg(); Class Car
public: string make
composition (has-a) string make; string model;
}; string model
• Rather than a Hybrid “is-a” Car we
might say Hybrid “has-a” car in it, double Car::compute_mpg()
{
plus other stuff if(speed > 55) return 30.0;
– Better example when we get to Lists, else return 20.0;
}
Queues and Stacks
• While it might not make complete class Hybrid { Class Hybrid
public: string _c.make
sense verbally, we could re-factor double compute_mpg();
our code the following ways… private: string _c.model
Car c_; // has-a relationship
string battery
• Interesting article I’d recommend };
string batteryType;

you read at least once: double Hybrid::compute_mpg()


– http://berniesumption.com/software/inh {
if(speed <= 15) return 45; // hybrid mode
eritance-is-evil-and-must-be-destroyed/ else return c_.compute_mpg();
}
24

Another Composition
class List{
• We can create a FIFO that "has-a" a List public:
List();
as the underlying structure void insert(int loc, const int& val);
int size();
• Summary: int& get(int loc);
void pop(int loc;)
– Public Inheritance => "is-a" relationship private:
– Composition => "has-a" relationship IntItem* _head;
};
– Private Inheritance => "as-a" relationship
"implemented-as"
Base Class

class FIFO
{ private:
List mylist;
public:
FIFO();
push_back(const int& val)
{ mylist.insert(size(), val); }
int& front();
{ return mylist.get(0); }
void pop_front();
{ mylist.pop(0); }
int size() // need to create wrapper
{ return mylist.size(); }
};

FIFO via Composition

You might also like