0% found this document useful (0 votes)
188 views

23 CPP Inheritance Cont

The document is a lecture summary on inheritance in C++. It discusses key concepts like inheritance establishing hierarchical relationships between classes, benefits like code reuse and polymorphism, and an example inheritance design for a stock portfolio. It also covers class derivation lists, method overriding, constructor and destructor calling order, polymorphism using pointers/references, and other inheritance rules.

Uploaded by

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

23 CPP Inheritance Cont

The document is a lecture summary on inheritance in C++. It discusses key concepts like inheritance establishing hierarchical relationships between classes, benefits like code reuse and polymorphism, and an example inheritance design for a stock portfolio. It also covers class derivation lists, method overriding, constructor and destructor calling order, polymorphism using pointers/references, and other inheritance rules.

Uploaded by

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

Lecture Participation Poll #22

Log onto pollev.com/cse374


Or
Text CSE374 to 22333

Lecture 22: C++ CSE 374: Intermediate

Inheritance
Programming Concepts and
Tools

1
Administrivia
HW 3 posted Friday -> Extra credit due date Wednesday Nov 25th @ 9pm
End of quarter due date Wednesday December 16th @ 9pm

CSE 374 AU 20 - KASEY CHAMPION 2


Inheritance in C++
Inheritance is the formal establishment of
hierarchical relationships between classes in order
to facilitate the sharing of behaviors
A parent-child “is-a” relationship between classes Java C++
- A child (derived class) extends a parent (base class) Superclass Base Class
Benefits: Subclass Derived Class
- Code reuse
- Children can automatically inherit code from parents
- Polymorphism
- Ability to redefine existing behavior but preserve the interface
- Children can override the behavior of the parent
- Others can make calls on objects without knowing which part of the inheritance tree
it is in
- Extensibility
- Children can add behavior

CSE 374 AU 20 - KASEY CHAMPION 3


Inheritance Design Example: Stock Portfolio
Stock DividendStock Cash

A portfolio represents a person’s symbol_


total_shares_
symbol_
total_shares_
amount_
GetMarketValue()
financial investments total_cost_
current_price_
total_cost_
current_price_
- Each asset has a cost (i.e. how much was dividends_
GetMarketValue()
paid for it) and a market value (i.e. how GetProfit() GetMarketValue()
much it is worth) GetCost() GetProfit()
- The difference between the cost and market value is GetCost()
the profit (or loss)
- Different assets compute market value in Stock DividendStock
different ways
symbol_ symbol_
- A stock that you own has a ticker symbol (e.g. total_shares_ total_shares_
“GOOG”), a number of shares, share price paid, total_cost_ total_cost_
and current share price current_price_ current_price_
- A dividend stock is a stock that also has dividend dividends_
Asset (abstract) GetMarketValue()
payments
GetProfit() GetMarketValue()
- Cash is an asset that never incurs a profit or loss GetCost() GetProfit()
GetMarketValue() GetCost()
GetProfit()
GetCost() Cash
amount_
GetMarketValue()
CSE 374 AU 20 - KASEY CHAMPION 4
Class Derivation List
Comma-separated list of classes to inherit from: public: visible to all other classes
#include "BaseClass.h" protected: visible to current class
class Name : public BaseClass {
and its derived classes
...
}; private: visible only to the current
class
- Focus on single inheritance, but multiple inheritance possible
Use protected for class members
#include "BaseClass.h"
#include "BaseClass2.h" only when:
class Name : public BaseClass, public BaseClass2 { - Class is designed to be extended by derived
... classes
}; - Derived classes must have access but clients
Almost always use “public” inheritance should not be allowed
- Acts like extends does in Java
- Any member that is non-private in the base class is the same in the derived
class; both interface and implementation inheritance
- Except that constructors, destructors, copy constructor, and assignment operator are never
inherited
- We’ll only use public inheritance in this class
CSE 374 AU 20 - KASEY CHAMPION 5
Method Override
Overrides - If a derived class defines a method with the same method name and argument types
as one derived in the base class, it is overridden
- replaces the base class version with the most closely defined version

If you want to use the base-class code, specify the base class when making a method call
- class::method(…)
- Like Java “super” but C++ doesn’t have “super” because of multiple inheritance

CSE 374 AU 20 - KASEY CHAMPION 6


Constructing and Destructing
Constructor of base class gets called before constructor of derived class
- default (zero-argument) constructor unless you specify a different on after the : in the constructor
- Initializer syntax: Foo::Foo(…) : Bar (args); it(x) { … }

Destructor of base class gets called after destructor of derived class


Constructors & destructors “extend” rather than “override”
- same as Java

class Derived : public Base {


public:
double m_cost;
Derived(double cost = 0.0, int id = 0)
: Base { id }, // Call Base(int) constructor
m_cost { cost } // assign prameter values
{
}
double getCost() const (return m_cost; }
}; CSE 374 AU 20 - KASEY CHAMPION 7
Polymorphism in C++
In Java: PromisedType var = new ActualType();
- var is a reference (different term than C++ reference) to an object of ActualType on the Heap
- ActualType must be the same class or a subclass of PromisedType

In C++: PromisedType* var_p = new ActualType();


- var_p is a pointer to an object of ActualType on the Heap
- ActualType must be the same or a derived class of PromisedType
- (also works with references)
- PromisedType defines the interface (i.e. what can be called on var_p), but ActualType may determine which version
gets invoked

polymorphism is the ability to access different objects through the same interface

CSE 374 AU 20 - KASEY CHAMPION 8


Other Inheritance Rules
Static fields
- the “static” keyword means only ONE variable for all object instances of this class, not one per object like normal
fields
- can be used to generate unique ids for each instance of an object or keep a count of how many instances have been
created

deleted constructors
- C++ automatically generates a “copy constructor” for your class if you do not provide one, however sometimes you
want to prevent copies. (EX: copying bank account objects). Instead declare a copy constructor in the header file and
set the constructor “= delete;” which means we delete anything created and prevent it from being used anywhere else

CSE 374 AU 20 - KASEY CHAMPION 9


Up/Down Casting
Up Casting
- An object of a derived class cannot be cast to an object of a base class
- for the same reason a struct T1 {int x,y,z;} cannot be cast to type struct T2 {int x,y;} (different size)
- a pointer to an object of a derived class can be cast to a pointer to an object of base class
- for the same reason a struct T1* can be cast to type struct T2* (pointers to location in memory have same size)
- After such an “upcast”, field access works fine

Down Casting
- C pointer-casts: unchecked; be careful
- Java: checkedl; may raise ClassCastException
- New: C++ has “all the above” (ie several different kinds of casts)
- if you use single-inheritance and know what you are doing, the C-style casts (same pointer, assume more about what is pointed to)V should work
fine for down casts

CSE 374 AU 20 - KASEY CHAMPION 10


Inheritance Design Example: Stock Portfolio
Stock DividendStock
symbol_ Stock dividends_
total_shares_ symbol_
total_cost_ total_shares_
current_price_ total_cost_ GetMarketValue()
current_price_ GetProfit()
GetMarketValue() GetMarketValue() GetCost()
GetProfit() GetProfit() PayDividend()
GetCost()
GetCost()

A derived class:
Inherits the behavior and state (specification) of the base class
Overrides some of the base class’ member functions (opt.)
Extends the base class with new member functions, variables (opt.)

CSE 374 AU 20 - KASEY CHAMPION 11


#ifndef BANKACCOUNT_H
#ifndef SAVINGSACCOUNT_H
#define BANKACCOUNT_H
#define SAVINGSACCOUNT_H
#include <iostream>
#include "BankAccount.h"
namespace bank {
namespace bank {
class BankAccount {
class SavingsAccount : public BankAccount {
public:
public:
explicit BankAccount(const std::string& accountHolder);
SavingsAccount(double interestRate, std::string name);
BankAccount(const BankAccount& other) = delete;
double getInterestRate() const;
// Accessors
int getBalance() const;
virtual void withdraw(int amount) override;
int getAccountId() const;
const std::string& getAccountHolder() const;
private:
bool isNewMonth(time_t* curTime);
// Modifier - add money.
void deposit(int amount);
double interestRate_;
time_t lastMonth_;
// different for every type of account,
int numTransactionsInMonth_;
// require derived classes to implement
};
virtual void withdraw(int amount) = 0;
}
protected:
// derived classes can modify the balance.
void setBalance(int balance);
#endif SavingsAccount.cc
private:
const std::string accountHolder_;
const int accountId_;
int balance_;

static int accountCount_;


};
}
#endif BankAccount.cc CSE 374 AU 20 - KASEY CHAMPION 12
#include <iostream>

Self Check using namespace std;

class A {
public:
A() { cout << "a()" << endl; }
~A() { cout << "~a" << endl; }
void m1() { cout << "a1" << endl; }
void m2() { cout << "a2" << endl; }
};

// class B inherits from class A


b() class B : public A {
public:
B() { cout << "b()" << endl; }
m1. a1 ~B() { cout << "~b" << endl; }
void m2() { cout << A::m2();
m2. a2 << "b2" << endl; }
void m3() { cout << "b3" << endl; }
b2 };
m3.
b3 int main() {
//B* x = new B();
A* x = new B();
x->m1();
x->m2();
x->m3();
delete x;
}
CSE 374 AU 20 - KASEY CHAMPION 13
Abstract Classes
Sometimes we want to include a function in a class but only implement it in derived
classes
- In Java, we would use an abstract method
- In C++, we use a “pure virtual” function
- Example: virtual string noise() = 0;

virtual string noise() = 0;


A class containing any pure virtual methods is abstract
- You can’t create instances of an abstract class
- Extend abstract classes and override methods to use them

A class containing only pure virtual methods is the same as a Java interface
- Pure type specification without implementations

CSE 374 AU 20 - KASEY CHAMPION 14


Virtual Methods
class C {
virtual t0 m(t1, t2,…,tn) = 0;

};
Code for class functions stored in a function table
- look up the functions for a class based on object type
- If we want an object to look in the function table for the constructed class, not the variable type (often a base type) we make the
function “virtual”

a non-virtual method call is resolved using the compile-time type of the receiver expression
a virtual method call is resolved using the run-time class of the receiver object (what the expression evaluates to)
- Aka: dynamic dispatch

A method-call is virtual if the method called is market virtual or overrides a virtual method
- so “one virtual” somewhere up in the base-class chain is enough, but it’s better style to be more explicit and repeat “virtual”

pure virtual functions


- to maximize code sharing sometimes you will need “theoretical” objects or functions that will be shared across more specific
implementations. (EX: “bank account” is too general to exist, instead you use it to share code across “checking account” and “business
account”)
- When defining abstract classes sometimes you want to declare a function that must be implemented by all derived classes, you can
create a virtual function:
- virtual void withdraw(int amount) = 0 ;

CSE 374 AU 20 - KASEY CHAMPION 15


Dynamic Dispatch
Usually, when a derived function is available for an object, we want the derived function to be
invoked
- This requires a run time decision of what code to invoke

A member function invoked on an object should be the most-derived function accessible to the
object’s visible type
- Can determine what to invoke from the object itself

Example:
- void PrintStock(Stock* s) { s->Print(); }

Calls the appropriate Print() without knowing the actual type of *s, other than it is some sort of Stock
Functions just like Java
Unlike Java: Prefix the member function declaration with the virtual keyword
- Derived/child functions don’t need to repeat virtual, but was traditionally good style to do so
- This is how method calls work in Java (no virtual keyword needed)
- You almost always want functions to be virtual

CSE 374 AU 20 - KASEY CHAMPION 16


Dynamic Dispatch
Stock.cc
double Stock::GetMarketValue() const { #include "Stock.h"
return get_shares() * get_share_price(); #include "DividendStock.h"
}
DividendStock dividend();
double Stock::GetProfit() const { DividendStock* ds = &dividend;
return GetMarketValue() – GetCost(); Stock* s = &dividend; // why is this allowed?
}
// Invokes DividendStock::GetMarketValue()
ds->GetMarketValue();
double DividendStock::GetMarketValue() const {
return get_shares() * get_share_price() + dividends_; // Invokes DividendStock::GetMarketValue()
} s->GetMarketValue();

double "DividendStock"::GetProfit() const { // inherited // invokes Stock::GetProfit(),


return GetMarketValue() – GetCost(); // since that method is inherited.
} // Stock::GetProfit() invokes
// DividendStock::GetMarketValue(),
DividendStock.cc // since that is the most-derived accessible
function.
s->GetProfit();

CSE 374 AU 20 - KASEY CHAMPION 17


Most-Derived Self-Check
class A { void Bar() {
public: A* a_ptr;
virtual void Foo(); C c;
};
E e;
class B : public A {
public: // Q1:
virtual void Foo(); a_ptr = &c; Q1 Q2
}; a_ptr->Foo();
A. A B
class C : public B { // Q2:
}; a_ptr = &e; B. A D
a_ptr->Foo();
class D : public C { B B
} C.
public:
virtual void Foo();
}; D. B D

class E : public C {
};
CSE 374 AU 20 - KASEY CHAMPION 18
Questions

CSE 374 AU 20 - KASEY CHAMPION 19


RAII
char* return_msg_c() {
"Resource Acquisition is Initialization" int size = strlen("hello") + 1;
Design pattern at the core of C++ char* str = malloc(size);
strncpy(str, "hello", size);
When you create an object, acquire resources return str;
- Create = constructor }
- Acquire = allocate (e.g. memory, files)

When the object is destroyed, release resources std::string return_msg_cpp() {


std::string str("hello");
- Destroy = destructor
return str;
- Release = deallocate }
When used correctly, makes code safer and easier
to read using namespace std;
char* s1 = return_msg_c();
cout << s1 << endl;
string s2 = return_msg_cpp();
cout << s2 << endl;

CSE 374 AU 20 - KASEY CHAMPION 20


Compiler Optimization
The compiler sometimes uses a “return by value optimization” or “move semantics” to
eliminate unnecessary copies
- Sometimes you might not see a constructor get invoked when you might expect it

Point foo() {
Point y; // default ctor
return y; // copy ctor? optimized?
}

Point x(1, 2); // two-ints-argument ctor


Point y = x; // copy ctor
Point z = foo(); // copy ctor? optimized?

CSE 374 AU 20 - KASEY CHAMPION 21


Namespaces
Each namespace is a separate scope
- Useful for avoiding symbol collisions!

Namespace definition:
- namespace name {
// declarations go here
}
- Doesn’t end with a semi-colon and doesn’t add to the indentation of its contents
- Creates a new namespace name if it did not exist, otherwise adds to the existing namespace (!)
- This means that components (e.g. classes, functions) of a namespace can be defined in multiple source files

Namespaces vs classes
- They seems somewhat similar, but classes are not namespaces:
- There are no instances/objects of a namespace; a namespace is just a group of logically-related things (classes, functions,
etc.)
- To access a member of a namespace, you must use the fully qualified name (i.e. nsp_name::member)
- Unless you are using that namespace
- You only used the fully qualified name of a class member when you are defining it outside of the scope of the class definition
CSE 374 AU 20 - KASEY CHAMPION 22
Const
C++ introduces the “const” keyword which declares a value that cannot change
const int CURRENT_YEAR = 2020;

CSE 374 AU 20 - KASEY CHAMPION 23

You might also like