210 likes | 230 Views
Object Oriented Programming. Elhanan Borenstein borens@tau.ac.il. Lecture #6. Agenda. Operator Overloading – Cont’ Inheritance – Part 1. Operators Overloading. Operators Overloading. Operator Overloading Example.
E N D
Object OrientedProgramming Elhanan Borenstein borens@tau.ac.il Lecture #6
Agenda • Operator Overloading – Cont’ • Inheritance – Part 1
Operators Overloading Operator Overloading Example • Most operators cannot be automatically applied to objects though. (which can?) • However… we can define (overload) all available operators for classes too. • For example: class CPoint { int m_x, m_y; public: CPoint(int ax, int ay):m_x(ax), m_y(ay){} CPoint operator+(const CPoint& p) const;}; CPoint CPoint::operator+(const CPoint& p) const{ return CPoint(m_x + p.m_x, m_y + p.m_y);}
Operators Overloading Guidelines • An operator should be overloaded only when its behavior is obvious. Otherwise, a function should be used. • An overloaded operator should work in an analogous manner to the fundamental types. It should also have the same behavior. • Efficiency is essential: • Object parameters will pass ByRef • Object parameters that should not be changed will be defined as const • An operator that returns a local object should return it ByVal (preferably as a temp object within the return command) • Operators that returns the activating object or an object that was passed as a parameter should return it ByRef
Operators Overloading Methods (Member Functions) vs. Friend Functions • Operators can be overloaded in two manners: 1) As a method (member function) – An activating object is mandatory (parameters are optional) • The assignment operator can be overloaded only as a method. 2) As a global function - Only parameters • We will usually prefer to define the function as a friend function • Access to private data members • Declaration within the class • In some cases, we must use global function rather than a method. • When using a global function, there is always an additional parameter. (the first parameter will substitute for the activating object)
Operators Overloading Example • The CArray class.
Operators Overloading The ->, * Operators for Smart Pointer void func1(const Data* p);void func2(const Data& d);void main() { Data d; DataPtr p = &d; p->Init(); func1(p); func2(*p); } class Data { … public: void Init(){…}}; class DataPtr{ Data* pd; public: DataPtr(Data* p) : pd(p){ } Data* operator->() { return pd; } Data& operator*() { return *pd; } operator Data*() { return pd; }};
Inheritance Motivation Inheritance is one of the fundamental features of OOP. • In many cases we wish to extend an existing class (without replicating its source code), but … • We may be unable (or unwilling) to change the original base class: • The existing base class is still in use in its original form. • The original base class works fine (and we do not want to introduce new bugs) • There is no access to the original class source code (only the .obj and header files exists) • There are similar entities (with a common base) we wish to represent. (polymorphism) • The resulting code is easier to read and maintain and does not include redundant code
Inheritance Example class Base1 { int var1; public: Base1() {…} // constructor void OldFunc() {…} void Init() {…}}; class Derived1 : [public|protected|private] Base1{ int var2; public: Derived1() {…} // constructor void Init() {…} // override void Do(){…}};
Inheritance The Logic behind Inheritance • When inheriting a class, we inherit all its members and they will be included in the derived class: • Somewhat similar to object data members (embedded): • To differentiate, we can check the logics behind the implemented entities: • Inheritance: The derived class is a type of the base class. • Inner class: The inner class is a part of the external class. Base (father) Derived (son) (SIZE?) Additions Additions inner object embedding class
Inheritance Understanding Inheritance - Example class GraphicItem { int color; public: GraphicItem() {…} // constructor void Draw() {…} void ChangeColor(int n_clr) {…}}; … GraphicItem G, *pG;CPoint P, *pP;… G = P; P = G; pG = pP; pP = pG; … class CPoint : public GraphicItem{ int m_x, m_y; public: CPoint() {…} // constructor void Draw() {…} // override void Align(){…}};
Inheritance Inheritance Concepts • Inheritance is a logical specification (narrowing) of an entity, but… usually a physical extension of it. • The derived class can override methods that were inherited from the base class. • In this lecture, we will focus on public inheritance. • When inheriting a class, we inherit all its members - partial inheritance is not possible. • …However, we may not be able to access all of them.
Inheritance Accessing the Base Class Data Members • All the data members of the base class also exists in the derived class. But…: • There are cases where we cannot access these members. • They will still be included in the derived object size. • When won’t we be able to access the base class members: • Hiding – The derived class has defined a data member with the same name. We can still access the hidden data member using its full name (base_class::member) • Private Permissions – Any private member of the base class cannot be accessed in the derived class. Note: the private data member is still included in the derived class (and can be accessed using a public method of the base class). • A good design, will include in the base class only data members that are common (and can be accessed) by all derived classes.
Inheritance Using the Base Class Member Functions • The derived class also inherit all the base class methods. • The derived class can override inherited methods. • When activating a method of an object from the derived class: > If the inherited method was not overridden the base method (from the base class) will be activated. > If the method was overridden in the derived class, the method of the derived class will be activated. • We can still activate the base method using its full name. • It is very common to include a call to the base method from the derived method. • C’tor, D’tor and C.C. are the only methods that have a different behavior when inherited.
Inheritance C’tor and D’tor in Inherited Classes • C’tor and D’tor are not inherited (WHY?). • Constructing an object of the derived class, always activates first the C’tor of the base class (to create the base part of the object). • The order is thus as follows: • The C’tor of the base class is activated. • The additional data members of the derived class are created. • If some of the data members are objects the C’tor of each such object is activated. • The C’tor of the derived class is activated • The order of the D’tor’s activation is of course reversed. • What if the C’tor of the base class has parameters?
Inheritance C’tor and D’tor in Inherited Classes – Cont’ • If the C’tor of the base class has parameters we must use the initializationline (in an analogous manner to object data members): class CRect { CPoint pnt1, pnt2; public: CRect(int x1, int y1, …) : pnt1(x1,y1), pnt2(0,0) {…} // c’tor}; Embedded Objects class CGraphicRect : public GraphicItem{ … public: CGraphicRect(int color) : GraphicItem(color) {…} // c’tor}; Inheritance
Inheritance Assignment Operator (=) in Inherited Classes • The assignment operator in not inherited. • If the derived class did not implement the assignment operator, when copying, the base class assignment operator will not be activated but rather the default assignment operator of the derived class. • But… as part of the default assignment operator action, (when the base class members should be copied), the base class assignment operator will be activated. • Example: Stack
Inheritance Assignment Operator (=) in Inherited Classes • Rule of thumb: A derived class should implement an assignment operator only if it performs dynamic allocation. The same is true for the copy constructor and the destructor. • Remember the triplet: • Copy Constructor • Destructor • Assignment Operator • Example: AB.cpp