In this tutorial you will learn the basics of C++ and how to use super classes and sub classes. This will allow you to write a simple C++ program that you will then compile. The program will be a Visual Studio console application
About this Tutorial –
Objectives –
This course is aimed at students who need to get up to speed in C++. The course introduces object-oriented concepts and shows how they are implemented in C++. The course does not require awareness or familiarity with object-oriented programming techniques, but programming experience would be useful but not necessarily required.
Audience
Students who are new to object orientation (or programming) and need to learn C++.
Prerequisites
No previous experience in C++ programming is required. But any experience you do have in programming will help. Also no experience in Visual Studio is required. But again any experience you do have with programming development environments will be a valuable.
Experience using a contemporary OO language such as Java or C# would be useful but is not required.
Contents
The C++ course covers these topics and more:
- Introduction to C++: Key features of C++; Defining variables; Formulating expressions and statements; Built-in data types; Console input/output
- Operators and types: Assignment; Compound Assignment; Increment and decrement operators; Const declarations; Type conversions
- Going Further with Data Types: Enumerations; Arrays; Using the standard vector class; Using the standard string class; Structures
Quick Access
Overview
Estimated Time – 0.5 Hours
Not what you are looking? Try the next tutorial – Operator Overloading
Lab 1: Overview of inheritance
- Inheritance and OO
- Inheritance is a very important part of object-oriented development
- Terminology:
- For the “existing class”: Base class, superclass, parent class
- For the “new class”: Derived class, subclass, child class
- Potential benefits of inheritance:
- Improved OO model
- Faster development
- Smaller code base
- Superclasses and Subclasses
- The subclass inherits everything from the superclass (except constructors)
- You can define additional variables and methods
- You can override existing methods from the superclass
- You typically have to define constructors too
- Note: You can’t cherry pick or “blank off” superclass members
- The subclass inherits everything from the superclass (except constructors)
- Inheritance in C++
- Inheritance is not a requirement for C++ classes
- You can define a class that doesn’t inherit from anything
- There’s no Object class at the root of a global inheritance hierarchy (unlike Java and C#)
- C++ supports multiple inheritance
- A class can have any number of parent classes
- However… single inheritance is generally favoured over multiple inheritance
- i.e. just one parent class
- This is the way other OO languages do inheritance (e.g. Java, C#)
- Inheritance is not a requirement for C++ classes
- Defining a base class
- In Visual Studio, create a new C++ project named InheritanceApp in the student folder
- Define a class named Person with the following members:
- Data members for the person’s name and age
string name;
int age;
- A constructor, to initialize the name and age
Person::Person(const string & n, int a)
: name(n),
age(a)
{
cout << "\nPerson object created\n"; } - View code file.
- A ToString() method, to return a textual representation of the person's info
string Person::ToString() const
{
stringstream stm;
stm << name << " " << age; return stm.str(); } - A destructor, to output a simple message such as "goodbye from Person dtor"
Person::~Person()
{
cout << "\nGoodbye from Person dtor\n"; } - View code file.
- Data members for the person’s name and age
- In main(), write code to test your Person class
Person * p1 = new Person("Fred Flintstone", 68);
cout << p1->GetName() << endl; cout << p1->GetAge() << endl; cout << p1->ToString() << endl; - View code file.
Lab 2: Defining superclasses and subclasses
- Overview
- During OOA/OOD you decide how to organize classes in your inheritance hierarchy
- Generalization
- This is when you notice semantic similarities between classes in your design
- Factor the similarities into a common superclass
- Define subclasses that extend the superclass in appropriate ways
- Specialization
- This often occurs quite late during development, or if you are using a pre-provided class library or framework
- You notice a class that is almost what you want, but not quite
- Define a new class that extends the existing class as appropriate
- Sample Hierarchy
- Superclass Considerations
- To define a superclass, just define a regular class
- Although there are some issues you must consider...
- You can allow subclasses special access to some members
- Define members as "protected"
- You can allow subclasses to override some methods
- Define methods as "virtual"
- (Otherwise the methods cannot be overridden properly)
- You can defer a method implementation to subclasses
- Designate the method as "pure virtual"
- To define a superclass, just define a regular class
- Access Modifiers
- C++ supports 3 access levels for members in a class...
- public
- Accessible by anyone
- Methods and constants are often public
- private
- Accessible only by class itself
- Data and helper methods are usually private
- protected
- Accessible by class itself, and by subclasses
- Allow access to members that are hidden from general client code
- Defining a Superclass
- Here are the interesting parts of the BankAccount class
- This is a simplification for now...
class BankAccount
{
private:
string accountHolder;
private int id;
protected:
double balance;
// Class data ...
// Constructors ...
// Instance methods, including overridable methods if appropriate.
// Class methods ...
};
- This is a simplification for now...
- Note:
- balance is protected, so it can be accessed by subclasses
- Here are the interesting parts of the BankAccount class
- Defining a Subclass
- To define a subclass, use this syntax:
- Note the public keyword - this is significant!
class SavingsAccount : public BankAccount
{
// Additional data and methods ...
// Constructor(s) ...
// Overrides for superclass methods, if necessary ...
};
- Note the public keyword - this is significant!
- To define a subclass, use this syntax:
- Adding New Members
- The subclass inherits everything from the superclass
- (Except for constructors)
- The subclass can define additional members if it needs to...
class SavingsAccount : public BankAccount
{
private:
bool premium, goneOverdrawn;
static const double BASIC_INTEREST_RATE;
static const double PREMIUM_INTEREST_RATE;
static const double GUARANTEED_LIMIT;
public:
void applyInterest()
{
if (balance < 0) cout << "Sorry mate, no interest if you're overdrawn" << endl; else if (premium && !goneOverdrawn) balance *= (1 + PREMIUM_INTEREST_RATE); else balance *= (1 + BASIC_INTEREST_RATE); } ... };
- The subclass inherits everything from the superclass
- Defining Constructors
- The subclass doesn't inherit constructors from superclass
- So, define constructor(s) in subclass, to initialize subclass data
- The subclass constructor must invoke the superclass constructor, to initialize superclass data
- You do this via the member initialization list
class SavingsAccount : public BankAccount
{
public:
...
SavingsAccount(const string & accountHolder, bool premium)
: BankAccount(accountHolder),
premium(premium)
{
// Any additional subclass initialization here.
}
...
};
- You do this via the member initialization list
- The subclass doesn't inherit constructors from superclass
- Virtual Methods
- The subclass can override superclass instance methods that are defined with the virtual keyword
- To provide a different (or supplementary) implementation
- No obligation
- If a subclass overrides a virtual method:
- The signature must match the superclass method signature
- The return type must be the same
- The access level must be the same, or less restrictive
- An override can call the original superclass method, to leverage existing functionality
- Via BaseClassName::methodName(params)
- Examples of overriding methods:
class BankAccount
{
public:
virtual double withdraw(double amount) { ... }
virtual string toString() { ... }
...
class SavingsAccount : public BankAccount
{
public:
double withdraw(double amount)
{
BankAccount::withdraw(amount);
if (balance < 0) goneOverdrawn = true; return balance; } string toString() { string str = BankAccount::toString() + ", " + (premium ? "Premium, " : "Normal, ") + (goneOverdrawn ? "gone overdrawn" : "not gone overdrawn"); return str; } ...
- The subclass can override superclass instance methods that are defined with the virtual keyword
- Virtual Destructors
- If a superclass defines one or more virtual methods...
- Then the superclass should also define a virtual destructor
- Ensures that if derived classes define their own destructor, the correct destructor will always be called when objects are deleted
- Example:
class BankAccount
{
public:
virtual ~ BankAccount();
...
};
- If a superclass defines one or more virtual methods...
- Defining a derived class
- Define a class named Student that inherits from Person (i.e. a student "is a kind of" person). Implement the following additional details in Student:
- Data members for the student's subject (etc.)
string subject;
int grade;
- View code file.
- A constructor, to initialize a student (call the base constructor via the initialization list)
Student::Student(const string & n, int a, const string & s, int g)
:Person(n, a),
subject(s),
grade(g)
{
cout << "\nStudent object created\n"; } - A ToString() method, to return a textual representation of the student's info. Make use of the ToString() method in the base class, to format inherited data
string Student::ToString() const
{
stringstream stm;
stm << Person::ToString() << " " << subject << " " << grade; return stm.str(); } - View code file.
- A destructor, to output a simple message such as "goodbye from Student dtor"
Student::~Student()
{
cout << "\nGoodbye from Student dtor\n"; } - View code file.
- Data members for the student's subject (etc.)
- In main(), write some simple code to test your Student class. Observe the order in which constructors and destructors fire.
Student * s1 = new Student("Bam Bam", 12, "Hunting Mammoths", 9);
cout << s1->GetName() << endl; cout << s1->GetAge() << endl; cout << s1->ToString() << endl; - View code file.
- Define a class named Student that inherits from Person (i.e. a student "is a kind of" person). Implement the following additional details in Student:
Lab 3: Polymorphism
- What is Polymorphism?
- Greek for "many forms"
- In an OO context:
- You can have many different "kinds" of object (e.g. many different kinds of bank accounts)
- Your application can treat them all in the same way
- Your application doesn't need to know which particular kind of object it's using at any given moment
- The Principle of Substitutability
- Polymorphism is facilitated via "substitutability"
- A superclass pointer/reference can refer to any subclass object
void demoPolymorphism() {
BankAccount * sa = new SavingsAccount("Mickey", true);
BankAccount * ca = new CurrentAccount("Donald", 50);
processAccount(sa);
processAccount(ca);
}
void processAccount(BankAccount * account) {
...
// The compiler knows "account" points to a BankAccount object or some subclass,
// but it doesn't know which particular subclass.
// Therefore the compiler only lets you access members defined in BankAccount.
// You can't access SavingsAccount-specific or CreditAccount-specific members.
// This is good - your code is more "general purpose", so you won't have to modify
// your code if someone defines a new kind of BankAccount subclass in the future.
...
}
- A superclass pointer/reference can refer to any subclass object
- Polymorphism is facilitated via "substitutability"
- Polymorphism in Action
- What happens when you invoke an instance method via a superclass pointer/reference?
- The "correct" version of the method is invoked, depending on the actual type of object currently pointed to
- Specifically, this is what polymorphism boils down to:
- If the pointer/reference actually points to a subclass object...
- And that subclass has overridden the method...
- The subclass's version of the method is called
void processAccount(BankAccount * account)
{
account->withdraw(200);
account->deposit(300);
cout << account->toString() << endl; }
- What happens when you invoke an instance method via a superclass pointer/reference?
- Polymorphic Collections
- A polymorphic collection (or array) can hold different types of subclass objects
- Allows you to insert any type of subclass object into the collection/array
- When you access items in the collection/array, you are working with superclass pointers
List<BankAccount*> accounts;
accounts.push_front(new SavingsAccount("Pluto", true));
accounts.push_front(new CurrentAccount("Goofy", 50));
...
for (list<BankAccount*>::iterator it = accounts.begin(); it != accounts.end(); it++)
{
processAccount(*it);
}
- When you access items in the collection/array, you are working with superclass pointers
- Run-Time Type Information (RTTI)
- Classes that have virtual methods support run-time type information (RTTI)
- Allows client code to determine the exact type of an object
- Similar to instanceof in Java, and is in C#
- To use RTTI in your client code:
- Classes that have virtual methods support run-time type information (RTTI)
- Defining another derived class
- Define an Employee class. An employee is a kind of person, with these additional features:
- A salary and a job grade
private:
int jobgrade;
protected:
double salary;
- View code file.
- A method to give the employee promotion (increase salary by £1000 per job-grade-rise)
void Employee::Promote()
{
salary += jobgrade * 1000;
}
- A method to calculate the number of years to retirement (everyone retires at 65 currently)
int Employee::YearsToRetire() const
{
return 65 - GetAge();
}
- View code file.
- Housekeeping methods (constructor(s), destructor, ToString(), etc.)
Employee::Employee(const string & n, int a, double sal, int jg)
: Person(n, a),
salary(sal),
jobgrade(jg)
{
cout << "\nEmployee object created\n"; } Employee::~Employee() { cout << "\nGoodbye from Employee dtor\n"; } string Employee::ToString() const { stringstream stm; stm << Person::ToString() << " " << salary << " " << jobgrade; return stm.str(); } - View code file.
- A salary and a job grade
- Test this new class from main()
Employee * d1 = new Employee("Barney", 32, 34000, 3);
cout << d1->GetName() << endl; cout << d1->GetSalary() << endl; cout << d1->ToString() << endl; d1->Promote();
cout << d1->GetSalary() << endl; cout << d1->YearsToRetire() << endl; - View code file.
- Define an Employee class. An employee is a kind of person, with these additional features:
Lab 4: Pure virtual methods
- Overview
- When you define an inheritance hierarchy, the superclass must list all the methods that will be available to the client
- The problem is, the superclass might not know how to actually implement some of these methods
- For example, the implementation details might vary completely across all the subclasses
- In such cases, declare the method as "pure virtual"
- The superclass does not provide a method body
- Instead, each subclass is obliged to implement the method
- Note, this is equivalent to abstract methods in Java and C#
- When you define an inheritance hierarchy, the superclass must list all the methods that will be available to the client
- Defining Pure Virtual Methods
- In the superclass:
class BankAccount
{
...
virtual string getTermsAndConditions() = 0;
virtual double getGuaranteedLimit() = 0;
...
};
- The subclass is obliged to override pure-virtual methods:
class SavingsAccount : public BankAccount
{
...
string getTermsAndConditions() { ... }
double getGuaranteedLimit() { ... }
...
};
- In the superclass:
- Abstract Classes
- If a class defines one or more pure-virtual methods...
- The class is "abstract"
- You are not allowed to create an instance of that class (because some of its methods are unfulfilled)
- This also applies for a subclass that hasn't overridden all the pure-virtual methods from the superclass
- ...because the methods remain unfulfilled
- Note for Java and C# programmers:
- If a class defines one or more pure-virtual methods...
Well done. You have completed the tutorial in the C++ course. The next tutorial is
12. Operator Overloading
Copyright © 2016 TalkIT®
If you would like to see more content like this in the future, please fill-in our quick survey.