[go: up one dir, main page]

0% found this document useful (0 votes)
73 views48 pages

Introduction To C Part 3

The document provides an introduction to defining classes in C++, including class inheritance, access control keywords (public, private, protected), and virtual functions. It discusses creating a Rectangle class with length and width data members and an Area() method. It covers class constructors and destructors, and how they are used to initialize objects and clean up resources. Default constructors and values are also explained.

Uploaded by

nitin rakh
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)
73 views48 pages

Introduction To C Part 3

The document provides an introduction to defining classes in C++, including class inheritance, access control keywords (public, private, protected), and virtual functions. It discusses creating a Rectangle class with length and width data members and an Area() method. It covers class constructors and destructors, and how they are used to initialize objects and clean up resources. Default constructors and values are also explained.

Uploaded by

nitin rakh
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/ 48

Introduction to C++: Part 3

Tutorial Outline: Part 3

 Defining Classes
 Class inheritance
 Public, private, and protected access
 Virtual functions
A first C++ class
 Open project Basic_Rectangle.

 We’ll add our own custom class to this project.

 A C++ class consists of 2 files: a header file (.h) and a source file (.cpp)

 The header file contains the definitions for the types and names of members, methods, and
how the class relates to other classes (if it does).

 The source file contains the code that implements the functionality of the class

 Sometimes there is a header file for a class but no source file.


Using Eclipse

 An IDE is very useful for setting up code that follows patterns and configuring the build
system to compile them.

 This saves time and effort for the programmer.

 Right-click on the Basic_Rectangle project and choose NewClass


 Give it the name
Rectangle and click
the Finish button.

 Open the new files


Rectangle.h and
Rectangle.cpp
Rectangle.h
Class name

keyword

Curly brace

Access
control

Curly brace
and a
semi-colon.
Default declared methods
 Rectangle();
 A constructor. Called when an object of this class is
created.

 ~Rectangle();
 A destructor. Called when an object of this class is
removed from memory, i.e. destroyed.
 Ignore the virtual keyword for now.
Rectangle.cpp
Header file included

Class_name:: pattern indicates


the method declared in the header
is being implemented in code
here.

Methods are otherwise regular


functions with arguments () and
matched curly braces {}.
Let’s add some functionality
 A Rectangle class should store a
length and a width.
 To make it useful, let’s have it
supply an Area() method to
compute its own area.

 Edit the header file to look like the


code to the right.
Encapsulation

 Bundling the data and area calculation for a rectangle into a


single class is an example of the concept of encapsulation.
The code for the two methods is needed

 Right-click in the Rectangle.h


window and choose
SourceImplement Methods
 Click Select All then click OK.
Fill in the methods
 Step 1: add some comments.
 Step 2: add some code.

 Member variables can be accessed as though they were passed to the method.
 Methods can also call each other.
 Fill in the Area() method and then write your own ScaledArea(). Don’t forget to compile!
Using the new class

 Open Basic_Rectangle.cpp  We’ll do this together…


 Add an include statement for
the new Rectangle.h

 Create a Rectangle object


and call its methods.
Special methods
 There are several methods that deal with creating and
destroying objects.

 These include:
 Constructors – called when an object is created. Can have many defined per class.

 Destructor – one per class, called when an object is destroyed

 Copy – called when an object is created by copying an existing object

 Move – a feature of C++11 that is used in certain circumstances to avoid copies.


Construction and Destruction

 The constructor is called when an  The destructor is called when an


object is created. object goes out of scope.
 Example:
 This is used to initialize an object: void function() {
 Load values into member variables ClassOne c1 ;
 Open files }
 Connect to hardware, databases,
networks, etc.  Object c1 is created when the
program reaches the first line of
the function, and destroyed when
the program leaves the function.
When an object is instantiated…

 The rT object is created in memory.


 When it is created its constructor is called to
do any necessary initialization.

 The constructor can take any number of


arguments like any other function but it
cannot return any values.

 What if there are multiple constructors?


 The compiler follows standard function overload rules. Note the constructor
has no return type!
A second constructor
rectangle.h rectangle.cpp
class Rectangle #include "rectangle.h“
{
public: /* C++11 style */
Rectangle(); Rectangle::Rectangle(const float width,
Rectangle(const float width, const float length):
const float length) ; m_width(width),
m_length(length)
/* etc */ {
}; /* extra code could go here */

 Adding a second constructor is similar to overloading a


function.
 Here the modern C++11 style is used to set the member
values – this is called a member initialization list
Member Initialization Lists
 Syntax: Colon goes here
MyClass(int A, OtherClass &B, float C):
Members assigned m_A(A),
and separated with m_B(B),
commas. The order m_C(C) {
doesn’t matter. /* other code can go here */
}

Additional code can be


added in the code
block.
#include <iostream>
And now use both constructors
using namespace std;

 Both constructors are now used. #include "Rectangle.h“


The new constructor initializes the
int main(int argc, char** argv)
values when the object is created. {
 Constructors are used to:
Rectangle rT ;
 Initialize members rT.m_width = 1.0 ;
 Open files rT.m_length = 2.0 ;
 Connect to databases
cout << rT.Area() << endl ;
 Etc.
Rectangle rT_2(2.0,2.0) ;
cout << rT_2.Area() << endl ;

return 0;
}
Default values class Rectangle {
public:
Rectangle();
Rectangle(const float width,
 C++11 added the ability to define default const float length) ;
values in headers in an intuitive way.
Rectangle(const Rectangle& orig);
virtual ~Rectangle();
 Pre-C++11 default values would have been
coded into constructors. float m_length = 0.0 ;
float m_width = 0.0 ;
 If members with default values get their value
set in constructor than the default value is float Area() ;
float ScaledArea(const float scale);
ignored.
 i.e. no “double setting” of the value. private:

};
Default constructors and destructors
 The two methods created by Eclipse automatically class Foo {
are explicit versions of the default C++ constructors public:
and destructors. Foo() = delete ;
// Another constructor
// must be defined!
 Every class has them – if you don’t define them then Foo(int x) ;
empty ones that do nothing will be created for you by };
the compiler. class Bar {
 If you really don’t want the default constructor you can public:
delete it with the delete keyword. Bar() = default ;
 Also in the header file you can use the default keyword };
if you like to be clear that you are using the default.
Custom constructors and destructors

 You must define your own constructor when you want to initialize an
object with arguments.

 A custom destructor is always needed when internal members in the


class need special handling.
 Examples: manually allocated memory, open files, hardware drivers, database or
network connections, custom data structures, etc.
This class just has 2 floats as members which are
Destructors automatically removed from memory by the compiler.

 Destructors are called when an object is Rectangle::~Rectangle()


{
destroyed.
 Destructors have no return type. }
 There is only one destructor allowed per
class.
 Objects are destroyed when they go out
of scope.
 Destructors are never called explicitly by
the programmer. Calls to destructors are ~House() destructor
inserted automatically by the compiler.

House object
Destructors
 Example:

class Example { Example::Example(int count) {


public: // Allocate memory to store "count"
Example() = delete ; // floats.
Example(int count) ; values = new float[count];
}
virtual ~Example() ;
Example::~Example() {
// A pointer to some memory // The destructor must free this
// that will be allocated. // memory. Only do so if values is not
float *values = nullptr ; // null.
}; if (values) {
delete[] values ;
}
}
Scope
 Scope is the region where a variable is valid.
 Constructors are called when an object is created.
 Destructors are only ever called implicitly.

int main() { // Start of a code block


// in main function scope
float x ; // No constructors for built-in types
ClassOne c1 ; // c1 constructor ClassOne() is called.
if (1){ // Start of an inner code block
// scope of c2 is this inner code block
ClassOne c2 ; //c2 constructor ClassOne() is called.
} // c2 destructor ~ClassOne() is called.
ClassOne c3 ; // c3 constructor ClassOne() is called.
} // leaving program, call destructors for c3 and c1 ~ClassOne()
// variable x: no destructor for built-in type
Copy, Assignment, and Move Constructors
 The compiler will automatically create constructors to deal with copying, assignment, and
moving. NetBeans filled in an empty default copy constructor for us.

 How do you know if you need to write one?


 When the code won’t compile and the error message says you need one!
 OR unexpected things happen when running.

 You may require custom code when...


 dealing with open files inside an object
 The class manually allocated memory Rectangle rT_1(1.0,2.0) ;
 Hardware resources (a serial port) opened inside an object // Now use the copy constructor
Rectangle rT_2(rT_1) ;
 Etc.
// Do an assignment, with the
// default assignment operator
rT_2 = rT_1 ;
Templates and classes

 Classes can also be created via templates in C++

 Templates can be used for type definitions with:


 Entire class definitions
 Members of the class
 Methods of the class

 Templates can be used with class inheritance as well.

 This topic is way beyond the scope of this tutorial!


Tutorial Outline: Part 3

 Defining Classes
 Class inheritance
 Public, private, and protected access
 Virtual functions
Inheritance
 Inheritance is the ability to form a
hierarchy of classes where they
share common members and Molecule
methods.
 Helps with: code re-use, consistent
programming, program organization

Inorganic Organic
 This is a powerful concept!

Mineral Protein
Inheritance Superclass Base Class
 The class being derived from is referred
to as the base, parent, or super class.

 The class being derived is the derived, Molecule Subclass


child, or sub class.

 For consistency, we’ll use superclass


and subclass in this tutorial. A base class Inorganic Organic
is the one at the top of the hierarchy.

Mineral Protein
Inheritance in Action

 Streams in C++ are series of characters  Writing to the terminal is straightforward:


– the C+ I/O system is based on this
concept. cout << some_variable ;

 cout is an object of the class ostream. It  How might an object of class ofstream or
is a write-only series of characters that ostringstream be used if we want to write
prints to the terminal. characters to a file or to a string?

 There are two subclasses of ostream:


 ofstream – write characters to a file
 ostringstream – write characters to a string
Inheritance in Action

 For ofstream and ofstringstream the << operator is inherited from ostream
and behaves the same way for each from the programmer’s point of view.

 The ofstream class adds a constructor to open a file and a close() method.
 ofstringstream adds a method to retrieve the underlying string, str()

 If you wanted a class to write to something else, like a USB port…


 Maybe look into inheriting from ostream!
 Or its underlying class, basic_ostream which handles types other than characters…
Inheritance in Action
#include <iostream> // cout
#include <fstream> // ofstream
#include <sstream> // ostringstream

using namespace std ;


void some_func(string msg) {
cout << msg ; // to the terminal
// The constructor opens a file for writing
ofstream my_file("filename.txt") ;
// Write to the file.
my_file << msg ;
// close the file.
my_file.close() ;
ostringstream oss ;
// Write to the stringstream
oss << msg ;
// Get the string from stringstream
cout << oss.str() ;
}
Tutorial Outline: Part 3

 Defining Classes
 Class inheritance
 Public, private, and protected access
 Virtual functions
“There are only two things wrong with C++: The initial concept
and the implementation.”
Public, protected, private – Bertrand Meyer (inventor of the Eiffel OOP language)

class Rectangle
{
public:
 Public and private were added by Rectangle();
Rectangle(float width, float length) ;
NetBeans to the Rectangle class. virtual ~Rectangle();

float m_width ;
 These are used to control access float m_length ;

to parts of the class with float Area() ;


inheritance.
protected:

private:
};
C++ Access Control and Inheritance
Access public protected private
Same class Yes Yes Yes
Subclass Yes Yes No
Outside classes Yes No No

Inheritance
class Super {
public: class Sub : public Super {
int i; // in methods, could access
protected: // i and j from Parent only.
int j ; };
private:
int k ; Outside code
};
Sub myobj ;
Myobj.i = 10 ; // public - ok
Myobj.j = 3 ; // protected - Compiler error
Myobj.k = 1 ; // private - Compiler error
class A class B : public A
Inheritance public public A public

protected protected A protected

private private

 With inheritance subclasses have access


class C : public B
to private and protected members and
methods all the way back to the base public A public public B
class. protected A protected protected B
 Each subclass can still define its own
public, protected, and private members private
and methods along the way.
Single vs Multiple Inheritance A

 C++ supports creating relationships where a subclass


inherits data members and methods from a single B C
superclass: single inheritance
 C++ also support inheriting from multiple classes
simultaneously: Multiple inheritance D
 This tutorial will only cover single inheritance.
 With multiple inheritance a hierarchy like
 Generally speaking… this is possible to create…this is
 Multiple inheritance requires a large amount of design effort nicknamed the Deadly Diamond of
 It’s an easy way to end up with overly complex, fragile code Death.
 Java and C# (both came after C++) exclude multiple
inheritance on purpose to avoid problems with it.
C++ Inheritance Syntax
class Super {
 Inheritance syntax pattern: public:
class SubclassName : public SuperclassName int i;
protected:
int j ;
 Here the public keyword is used. private:
int k ;
 Methods implemented in class Sub can access any public or };
protected members and methods in Super but cannot access
anything that is private. class Sub : public Super {
// ...
};
 Other inheritance types are protected and private.
Square

 Let’s make a subclass of Rectangle called Square.

 Open the NetBeans project Shapes

 This has the Rectangle class from Part 2 implemented.

 Add a class named Square.

 Make it inherit from Rectangle.


Square.h Square.cpp
#ifndef SQUARE_H #include “Square.h"
#define SQUARE_H
Square::Square()
#include "Rectangle.h" {}

Square::~Square()
class Square : public Rectangle {}
{
public:
Square();
virtual ~Square();

protected:
 Note that subclasses are free to add any number
private: of new methods or members, they are not limited
}; to those in the superclass.
#endif // SQUARE_H

 Class Square inherits from class Rectangle


A new Square constructor is needed.

 A square is, of course, just a rectangle with equal length and width.
 The area can be calculated the same way as a rectangle.
 Our Square class therefore needs just one value to initialize it and it can
re-use the Rectangle.Area() method for its area.

 Go ahead and try it:


 Add an argument to the default constructor in Square.h
 Update the constructor in Square.cpp to do…?
 Remember Square can access the public members and methods in its superclass
Solution 1
#ifndef SQUARE_H #include “Square.h"
#define SQUARE_H
Square::Square(float length):
#include “Rectangle.h" m_width (length), m_length(length)
{

class Square : public Rectangle }


{
public:
Square(float width);  Square can access the public members in its superclass.
virtual ~Square();  Its constructor can then just assign the length of the side to the
Rectangle m_width and m_length.
protected:

private:  This is unsatisfying – while there is nothing wrong with this it’s
}; not the OOP way to do things.

#endif // SQUARE_H
 Why re-code the perfectly good constructor in Rectangle?
The delegating constructor class class_c {
public:
int max;
int min;
int middle;

 C++11 added a new constructor type class_c(int my_max) {


called the delegating constructor. max = my_max > 0 ? my_max : 10;
}
class_c(int my_max, int my_min) : class_c(my_max) {
min = my_min > 0 && my_min < max ? my_min : 1;
 Using member initialization lists you can }
call one constructor from another. class_c(int my_max, int my_min, int my_middle) :
class_c (my_max, my_min){
middle = my_middle < max &&
my_middle > min ? my_middle : 5;
 Even better: with member initialization }
lists C++ can call superclass };
constructors!

Square::Square(float length) :
Reference: Rectangle(length,length)
{
https://msdn.microsoft.com/en-us/library/dn387583.aspx
// other code could go here.
}
Solution 2
#ifndef SQUARE_H #include "Square.h"
#define SQUARE_H
Square::Square(float length) :
#include "Rectangle.h" Rectangle(length, length) {}

class Square : public Rectangle  Square can directly call its superclass constructor and let the
{ Rectangle constructor make the assignment to m_width and
public:
m_length.
Square(float width);
virtual ~Square();
 This saves typing, time, and reduces the chance of adding
protected: bugs to your code.
 The more complex your code, the more compelling this statement
private:
is.
};

#endif // SQUARE_H  Code re-use is one of the prime reasons to use OOP.
Trying it out in main()
#include <iostream>
 What happens behind the scenes
when this is compiled…. using namespace std;

sQ.Area() #include “Square.h"

int main()
Square class {
does not
implement Area() Square sQ(4) ;
so compiler looks
to superclass
// Uses the Rectangle Area() method!
cout << sQ.Area() << endl ;

Finds Area() in return 0;


Rectangle class.
}

Inserts call to
Rectangle.Area()
method in
compiled code.
More on Destructors
 When a subclass object is
removed from memory, its
Square object is
destructor is called as it is for any removed from
object. memory

 Its superclass destructor is than


~Square() is called
also called .

 Each subclass should only clean


up its own problems and let
~Rectangle() is
superclasses clean up theirs. called

You might also like