CIS 280X – Test 02 Review All things classes! / Operator Overloading / run-time type information Review of class concepts 1. General object-oriented programming concepts a. attribute member data in C++ i. aka instance or class variable - field is often used for an instance variable b. behavior member function in C++ i. aka instance or static method c. state (value of all the fields at an instant in time) d. encapsulation e. data hiding f. code reuse 2. Class declaration a. can use struct or class in declaration use struct if you are only declaring public fields (c-style data structure) use class if you are declaring a new abstract data type (ADT) remember to put a semicolon (;) following the closing curly brace of a class declaration/definition 3. Access specifiers: public, private, protected a. general rule is private data, public functions b. private functions can be created for use as utility functions c. private is the default access for a class d. public is the default access for a structure e. member functions versus standalone functions 4. Accessors and mutators a. accessor - “get” member function <data type> get<field name>( ); b. mutator - “set” member function void set<field name>( <parameter-list> ); 5. Keyword const at the end of a member function prototype a. used to indicate the function will NOT change a field in the class 6. static keyword - used to create a static (class) variable or class function a. one copy of a field/function shared by all objects of a class b. is accessible (if public) even if no object has been created c. can be accessed using unary scope resolution operator <class name>::<member> d. can be accessed using an object handle if an object exists 7. Class constructor a. it uses the class name as the identifier Circle (double r) / GradeBook (string class, string instructor) b. does not have a return type and cannot return a value c. default constructor provided by C++ doesn’t do anything d. if a constructor is created for a class the default constructor is no longer automatically provided e. a default constructor has an empty parameter list or provides default values for all the parameters f. constructors may be overloaded g. there can only be one default constructor h. constructor member initializer list i. follows closing right parenthesis of constructor ii. is preceded by a colon iii. example: Foo ( int a, int b ) : x(a), y(b) { <constructor body> } i. constructor must be declared public to be used by a client of a class j. purpose of a constructor is to initialize an object when it is created k. use keyword explicit when declaring a constructor with one parameter l. if you create an object using a default constructor, omit the () Circle c; GradeBook gb; 8. Class copy constructor a. every class has a copy constructor (if you don’t create one, a default copy constructor will be provided b. the default copy constructor provided by C++ does a simple memberwise copy c. you should provide a copy constructor if your class has a field that stores a pointer d. If you provide a copy constructor it should have a reference parameter <class name>( <class name> & <parameter> ) Example: Circle (Circle & otherCircle) 9. Class destructor a. destructor identifier is ~ <class name> (~ is a tilde) Example: ~Circle( ) b. a destructor does not have a return type and cannot have a parameter list c. there can only be one destructor in a class (cannot be overloaded) d. destructor does any required cleanup before memory is reclaimed by OS e. objects are generally “destroyed” in reverse of the order they were created f. if a class has any virtual methods, a virtual destructor should be included in the class virtual ~Circle( ); 10. Operators always available for a class a. = //assignment assignment does a memberwise copy by default (again, a shallow copy) b. . //member access operator c. -> //arrow operator 11. Object handles a. object name b. pointer to an object c. reference to an object 12. Circle c(2); Circle * cirPtr = &c; Circle & cirRef = c; //object name is c //& is the address of operator //note – no & before c! this pointer a. used in a class to refer to itself this-> / (*this). / *this b. cannot be accessed by static member functions c. *this dereferences the object itself (useful when a member function returns a reference to the object itself) d. implicit reference for non-static member functions and non-static member variables e. must be used to access a “shadowed” field Example: this -> name = name or (*this).name = name; Inheritance in C++ 1. 2. 3. 4. 5. 6. Inheritance provides a mechanism for creating a more specific version of an existing class inheritance promotes code reuse and extensibility (a basis for adding new functionality) an inheritance hierarchy is a base class and all it’s derived classes A -> AB -> ABC -> ABCD etc. a derived class “is-a” base class. The derived class is a more specific version of the base class a class hierarchy goes from general to specific as you move down the hierarchy “base” class and “derived” class – the derived class (aka subclass) inherits from the base class (aka superclass) a. class <derived class> : <access specifier> <base class> i. example: class CommissionEmployee : public Employee class CommissionEmployee inherits from class Employee using public inheritance b. access specifiers for inheritance are: public (used most often), protected, and private c. a derived class inherits all the members of it’s base class (except for constructors) d. a derived class can only directly access inherited members declared public or protected in the base class e. a client of a class can only access public members of the class f. public inheritance: all inherited members have the same access as in the base class g. protected inheritance: public -> protected, protected -> protected, private -> private h. private inheritance: public -> private, protected -> private, private -> private i. for protected and private inheritance, the access to the inherited members inside a member function of the derived class is the same as in the base class This is true for friend functions as well. j. a derived class constructor executes AFTER it’s base class constructor (chain of constructor calls) k. if there is no default constructor in a base class, the derived class must explicitly call the base class constructor and pass any required arguments: <base class name> ( <argument list> ) Example: SEmployee(string first, string last, double sal) : Employee(first, last, ssn) { setSalary(sal); } //base class is Employee, derived class is SEmployee If there is a default constructor in the base class you can let it be called implicitly or choose to call it explicitly <base class name>( ) Example: AB( int a ) : x(a) { } or AB( int a ) : A(), x(a) { } //base class A, derived class AB, x is a field in AB Repurposing (modifying) the functionality of an inherited member function 1. an inherited member function can be: a. “redefined” - simply recreate the function header but modify the body of the function so it behaves differently i. just like overriding but with static binding b. “overridden” - an overridden member function is a “redefined” virtual function i. dynamic binding – allows for the function executed to be based on the type of the object More about class member functions 1. a member function can be declared virtual. This is important for polymorphism (aiming a base class pointer or reference at a derived class object) 2. a member function can be a pure virtual member function virtual <function prototype> = 0; 3. a pure virtual member function is also known as an abstract member function 4. a class with a pure virtual function is called an abstract class – it cannot be used to create an object 5. An abstract class can be used declare a pointer or a reference variable. Example: Class A is an abstract class: Example: AB ab; A * aPtr = &ab; or AB ab; A & aRef = ab; 6. a class that does not have any pure virtual functions is a concrete class 7. if a derived class inherits a pure virtual function from it’s base class and does not implement it, the derived class will be an abstract class 8. a redefined or overridden member function can call the base class version of the function to do part of the work that needs to be done. Use <base class name>::<function invocation> Example: Employee::print() called in CEmployee derived class print() function. Polymorphism in C++ 1. 2. 3. 4. used with classes related by inheritance involves using a base class pointer or reference to access a derived class object for inheritance and polymorphism a derived class object “is-a” base class object polymorphism can be observed in C++ if: a. a derived class inherits a virtual function. The virtual function is overridden in the derived class. b. the virtual function in the derived is accessed using a base class pointer or reference c. Employee * ePtr; CEmployee ce( … ); ePtr=&ce; ePtr->print( ); //print() is the overridden virtual function Downcasting a base class pointer to a derived class pointer Allows a program to access derived class members [ members not in the base class(es) ] CEmployee * cePtr; BPCEmployee * bpcePtr; BPCEmployee bpce( … ); cePtr = &bpce; bpcePtr = dynamic_cast<BPCEmployee *>( cePtr ); //attempt to downcast a CE pointer to a BPCE pointer if (bpcePtr != nullPtr) //test to see if downcast was successful Using run-time type information ( RTTI ) 1. 2. 3. 4. include header file <typeinfo> operator typeid returns a reference to an object of type type_info typeid(emp01) use a reference to a type_info object to access the name() function: typeid(emp01).name() the name() function returns a string representing the name of the class for an object. The actual output depends on the compiler used. The output from some compilers is cryptic. Operator Overloading <type> operator <operator symbol> ( <parameter list> ); //prototype template for an overloaded operator 1. most operators in C++ can be overloaded. To use an operator on an object of a class you must define overloaded operator functionality except for the operators listed below. Note: you can overload these operators. a. = assignment operator b. & address of operator c. , comma operator 2. there are 4 operators which can NOT be overloaded a. . member access b. .* pointer to member c. :: scope resolution operator d. ?: conditional operator 3. in general, an operator can be overloaded in C++ as: a. a member function [leftmost or only operand must be an object or a reference to an object] b. a non-member function (often declared as a friend function) 4. operators ( ), [ ], -> must be overloaded as non-static member functions 5. you cannot change the following attributes of an operator a. precedence b. associativity c. “arity” (number of operands it uses) 6. 7. 8. you can not create new operators a binary operator can be overloaded as a member function with one parameter a binary operator can be overloaded as a non-member function with two parameters (one of those members must either be an object or a reference to an object. Examples of operator overloading (function prototypes) 1. binary overloaded operator as a member function: leftmost or only operand must be an object or reference to an object. If you want the left operand to be a primitive type you must overload the operator as a non-member function. //1 parameter //compare the object that calls the operator function to another object String A(”abc”); String B(“cab”); expression A < B should evaluate to true. //object A invokes the operator< function bool operator<(const String &) const; 2. binary overloaded operator as a non-member function (2 parameters) //overload stream insertion operator for PhoneNumber class friend std::ostream& operator<<( std::ostream&, PhoneNumber& ); PhoneNumber pn = new PhoneNumber(); cin >> pn; 3. unary overloaded operator as a member function with no parameters: //overload prefix increment operator for Date class Date& operator++(); 4. unary overloaded operator as a non-member function with no parameters: //overload prefix increment operator for Date class Date& operator++( Date&); 5. unary overloaded operator as a member function with one parameter: //overload postfix increment operator for Date class Date& operator++( int ); //dummy argument to distinguish between prefix and postfix modes 6. unary overloaded operator as a non-member function //overload postfix increment operator for Date class Date operator++( Date&, int );