C++ Classes: Headers, Constants, Static Members, Hiding, Pointers & Inheritance - Prof. Xi, Study notes of Computer Science

An overview of various concepts in c++ classes, including header files, constants, static members, information hiding, pointers, and inheritance. Topics covered include the use of header files to prevent duplicate inclusions, defining constants using #define and const, static class members, and the principle of query functions being defined as const. The document also discusses the concept of access specifiers (public, protected, private) and their impact on derived classes, as well as the use of pointers and references with inheritance.

Typology: Study notes

2011/2012

Uploaded on 06/04/2012

proschek
proschek 🇺🇸

3 documents

1 / 4

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
1
Class Inheritance in C++
Header Files
To prevent being included twice
#ifndef MY_HEADER
#define MY_HEADER
//your declarations
#endif
#include <iostream> : search in
include search path
2
#include
<iostream>
:
search
in
include
search
path
Used for system header files
#include “MyHeader.h”: search in current directory
May check include search path if not found there
Used for your own header files
Constants
#define BUFFERSIZE 100
BUFFERSIZE cannot be used as a variable
const int buffersize = 100;
const ClassName aConstantObject;
What if we invoke an operation on a constant object that can change its data members?
aConstantObject.setValue();
Only const member functions can be invoked!
int getValue() const {…} //Hi, I will not change data members!
const int getValue() {…}//The function’s return value is con st.
3
Meaningless for built-in types
But meaningful for user-defined types: getStudentRecord().setName()
Principle: Query functions (such as getValue()) should always be defined as const.
Principle: Passing by reference or by pointer should always be defined as constant if
you do not change it. Constant passing by reference is better than passing by value.
int compare( const Student& s1, const Student& s2)
Note: Constant data members of a class can only be initialized through the member
initialization list of the constructor.
Student(string name): _studentName(name) {…}
Static
// In Counter.h
class Counter{
public:
Counter(){ num++;}
static int getNum() { return num; } //Can only refer to static member num
private:
static unsigned num; //one copy per class
string name; //one copy per object
};
4
Static class data members are allocated on a per class basis
rather than a per object basis.
Static class function members can only refer to static d ata
members.
};
// In Counter.cpp
unsigned Counter::num = 0; // Defines and allocates num
Namespace
Prevent naming conflicts
C++ has a standard string class. But what if IBM also developed a string
class?
Declare namespace:
namespace IbmStringPackage {
class string{
//IBM im
p
lementation of strin
g
class
5
pg
}
}
Two ways to use IBM string class:
(1) Use IbmStringPackage::string as the class name
(2) Declare “using namespace IbmStringPackage;” first, then use string as class
name. But in this case, you cannot delare “using namespace std;”.
Function Overloading
Same function, but different signatures (return type, parameters)
One type of polymorphism
int max( int, int );
double max( double, double );
6
pf3
pf4

Partial preview of the text

Download C++ Classes: Headers, Constants, Static Members, Hiding, Pointers & Inheritance - Prof. Xi and more Study notes Computer Science in PDF only on Docsity!

Class Inheritance in C++

Header Files

 To prevent being included twice

ifndef MY_HEADER

define MY_HEADER

//your declarations

endif

 #include : search in “include search path”

 #include : search in include search path

─ Used for system header files

 #include “MyHeader.h”: search in current directory

─ May check include search path if not found there ─ Used for your own header files

Constants

 #define BUFFERSIZE 100 ─ BUFFERSIZE cannot be used as a variable  const int buffersize = 100;  const ClassName aConstantObject; ─ What if we invoke an operation on a constant object that can change its data members? aConstantObject.setValue(); ─ Only const member functions can be invoked!  int getValue() const {…} //Hi, I will not change data members!  const int getValue() {…}//The function’s return value is const.

─ Meaningless for built-in types ─ But meaningful for user-defined types: getStudentRecord().setName()  Principle: Query functions (such as getValue()) should always be defined as const.  Principle: Passing by reference or by pointer should always be defined as constant if you do not change it. Constant passing by reference is better than passing by value. ─ int compare( const Student& s1, const Student& s2)  Note: Constant data members of a class can only be initialized through the member initialization list of the constructor. ─ Student(string name): _studentName(name) {…}

Static

// In Counter.h class Counter{ public: Counter(){ num++;} static int getNum() { return num; } //Can only refer to static member num private: static unsigned num; //one copy per class string name; //one copy per object };

 Static class data members are allocated on a per class basis

rather than a per object basis.

 Static class function members can only refer to static data

members.

}; // In Counter.cpp unsigned Counter::num = 0; // Defines and allocates num

Namespace

 Prevent naming conflicts

─ C++ has a standard string class. But what if IBM also developed a string class?

 Declare namespace:

namespace IbmStringPackage { class string{ //IBM implementation of string class

p g } }

 Two ways to use IBM string class:

─ (1) Use IbmStringPackage::string as the class name ─ (2) Declare “using namespace IbmStringPackage;” first, then use string as class name. But in this case, you cannot delare “using namespace std;”.

Function Overloading

 Same function, but different signatures (return type, parameters)

 One type of polymorphism

int max( int, int ); double max( double, double );

Information Hiding (1/4)

class A{ public: //data and functions needed by clients (public interface). protected: //data and functions needed by derived classes. private: //data and function needed by class A only. };

 Why private?

─ Client programs do not need them. Only for implementation. ─ They are subject to future change. ─ For private data, client programs may misuse them and cause inconsistency

 Why protected?

─ Needed by derived classes. Derived classes are trusted, but client programs are not.

Information Hiding (2/4)

class DerivedClassName: access_specifier BaseClassName{ //…… }

 Access-specifier : {public, protected, private}

─ Default (no access_specifier) = private

 Public Inheritance, Protected Inheritance, Private Inheritance

 Access control rule: effect = the stricter one of access and base

Access control rule: effect the stricter one of access and base

public protected private

public public protected private

protected protected protected private

private X X X

Information Hiding (3/4)

 When should access be protected or private?

In some cases when you want to operate on data with more stringent requirements, you do not want to inherit the entire interface of the base. ─ For example, suppose you have a Dequeue class that contains operations to insert and delete elements at either end of the queue. Now you want to implement a Queue class, which one can only insert on the left and delete on the right. class Dequeue{ public: void insertL( int );

class Queue: private Dequeue{ public:

─ Note: “using” restores insertL() and removeR() public; others remain private.

void insertL( int ); void insertR( int ); int removeL(); int removeR(); protected: //internal data structure };

public: using Dequeue::insertL; using Dequeue::removeR; };

Information Hiding (4/4)

 When access should be protected or private?

─ In some cases when you only want to inherit the implementation of the operations in the base class, and you do not want to inherit any interface at all. ─ For example, suppose you have a Dequeue class that contains operations to insert and delete elements at either end of the queue. Now you want to implement a stack class, which one can only insert on the left and delete on the left. In addition, you want to use new operation names such as push and pop. class Dequeue{ public:

class Stack: private Dequeue{ public: void push ( int x )

─ “Using” must keep the access level the same as the base.

void insertL( int ); void insertR( int ); int removeL(); int removeR(); protected: int _left; int _right; };

{ insertL(x); }; int pop() {removeL(); }; bool full() { return _left == _right;} protected: using Dequeue::_left; using Dequeue::_right; };

Pointers/references & Inheritance

 Pointer (resp. reference) to an object of a derived class

vs. pointer (resp. reference) to an object of its base.

void foo(){ Manager m, *mPtr; Employee e, *ePtr;

ePtr = &m; // OK mPtr = &e; // Error. An employee may not be a manager. }

Advantages of Inheritance

 Factor out code that is common in multiple classes

─ Derived class inherits function and data members from base class ─ Derived class may add additional function or data members ─ Derived class may override inherited function members with new methods

 Reuse functions that operate on base-class objects

p j

─ Invoke function whose formal parameter is of (reference or pointer) to class C with actual parameter of (reference or pointer to) class derived from C.

 Represent domain relationships explicitly in code

─ Manager and employee

Function Overriding (cont)

int main(void){ Employee anEmployee(“John”, “Doe”, 235); Manager aManager(“Charles”, “Howell”, 235, 3);

anEmployee.print(cout); // invokes Employee::print() aManager.print(cout); // invokes Manager::print()

Employee* ePtr = &aManager;

 Operation vs. Method

─ Operations are over-ridden with new methods. ─ E.g., print is an operation; Employee::print and Manager::print are methods.

 It would be useful to be able to write functions that invoke an

operation on an object, as opposed to invoking a particular method.

p y g ; ePtr->print(cout); // invokes Employee::print() }

Quiz

void myPrint( Employee& empl ){ empl.print(cout); };

int main(void) { Employee anEmployee(“John”, “Doe”, 235); Manager aManager(“Charles” “Howell” 235 3);

 Which method got called?

─ Answer: Employee::print() ─ Reference is similar to pointer

Manager aManager( Charles , Howell , 235, 3);

myPrint(aManager); }