Constructor, Destructor, Accessibility and Virtual Functions 182.132 VL Objektorientierte Programmierung Raimund Kirner Mitwirkung an Folienerstellung: Astrit Ademaj
Agenda Constructor Destructors this pointer Inheritance / Accessibility Virtual functions
Class A class consists of: member data (usually private) member functions (usually public) the simplest class shall have at least two member functions: set data show data member data can be public, and member functions can be private
Member data initialization After an object is created: Standard ways for data initialization: Setting default constants Reading input from user (using cin >>)
Member data initialization - example class circle private: int xc, yc, radius ; void set (int x, int y, int r) xc = x; yc = y; radius = r; void get () cout << \Enter x coordinate: ; cin >> xc; cout << \Enter y coordinate: ; cin >> yc; cout << \Enter radius : ; cin >> radius; void draw () draw_circle(xc, yc, radius); int main() circle c1, c2; c1.set (15, 17, 8); c2.get (); c1.draw(); c2.draw()
Member data initialization during the object instantiation use a special member function called CONSTRUCTOR (ctor)
Constructor Constructor is a member function that has the same name as the class To use a constructor it has to be declared public Constructor can be used to initialize data members of a class Is called automatically when an object of the class is created (instantiated)
Constructor - example class circle private: int xc, yc, radius ; circle() xc = 25 ; yc = 25 ; radius = 5; void set (int x, int y, int r) xc = x; yc = y; radius = r; void get () cout << \Enter x coordinate: ; cin >> xc; cout << \Enter y coordinate: ; cin >> yc; cout << \Enter radius : ; cin >> radius; void draw () draw_circle(xc, yc, radius); int main() circle c1, c2; c1.set (15, 17, 8); c1.draw(); c2.draw()
Constructor Last example shows the constructor - i.e, the constructor that takes no arguments either due to All parameters have default values (showed in the example), or No parameters are required Constructor does not return a value (void) to whom should it!? int main() circle c1; // default ctor will be executed int main() circle c1(); /* declaration of function c1() that has a circle-object as return value */
Constructor If no constructor is defined, a compiler generates one: default constructor if you don t care how data are being initialized If user defines a no-argument constructor member data are initialized using the no-argument constructor
Initializer List class circle private: int xc, yc, radius ; circle() : xc(25), yc(25), radius(5) /* empty body */ void set (int x, int y, int r) xc = x; yc = y; radius = r; void get () cout << \Enter x coordinate: ; cin >> xc; cout << \Enter y coordinate: ; cin >> yc; cout << \Enter radius : ; cin >> radius; void draw () Initialization takes place before the function body Members initialized in the initializer list and initialized before the constructor is executed Why not initialize members in constructor body? draw_circle(xc, yc, radius); const member data initialization
Constructor with parameters class circle private: int xc, yc, radius ; circle( int x, int y, int r) : xc (x), yc(y), radius(r) /* empty body */ void set (int x, int y, int r) xc = x; yc = y; radius = r; void get () cout << \Enter x coordinate: ; cin >> xc; cout << \Enter y coordinate: ; cin >> yc; cout << \Enter radius : ; cin >> radius; void draw () draw_circle(xc, yc, radius); int main() circle c1(15,25,10); c1.draw();
Constructor overloading A class can have more than 1 constructor Overloaded constructors shall have different parameter lists circle(); circle (int x, int y, int r);
Constructor overloading class circle private: int xc, yc, radius ; circle() : xc(25), yc(25), radius(5) circle( int x, int y, int r) : xc (x), yc(y), radius(r) void set (int x, int y, int r) xc = x; yc = y; radius = r; void get () cout << \Enter x coordinate: ; cin >> xc; cout << \Enter y coordinate: ; cin >> yc; cout << \Enter radius : ; cin >> radius; void draw () draw_circle(xc, yc, radius); overloading Only one default constructor is allowed int main() circle c1(15,25,10); circle c2; c1.draw(); c2.draw();
Member function overloading Non-constructor member functions can also be overloaded set (int x, int y, int r) set (int x, int y) Must have unique parameter lists (as with constructors)
Member function overloading class circle private: int xc, yc, radius ; circle() : xc(25), yc(25), radius(5) void set (int x, int y, int r) xc = x; yc = y; radius = r; void set (int x, int y) xc = x; yc = y void draw () draw_circle(xc, yc, radius); overloading int main() circle c1; c1.set(15,15,10); c1.draw(); c1.set(20,20); c1.draw();
Data Initialization No-argument constructor - initialize with constant Constructor with arguments Useful feature Initialize the data with another object of the same type Default Copy Constructor need not to be created (its for free ) a constructor which takes one object as argument
Copy Constructor class circle private: int xc, yc, radius ; circle() : xc(25), yc(25), radius(5) circle( int x, int y, int r) : xc (x), yc(y), radius(r) void set (int x, int y, int r) xc = x; yc = y; radius = r; void get () cout << \Enter x coordinate: ; cin >> xc; cout << \Enter y coordinate: ; cin >> yc; cout << \Enter radius : ; cin >> radius; void draw () draw_circle(xc, yc, radius); int main() circle c1(15,25,10); circle c2(c1); circle c3 = c1; c1.draw(); c2.draw(); c3.draw();
Destructors Public member function automatically called when an object is deleted (e.g., when the program finishes) Destructor name is ~classname, e.g., ~circle It has no return type (to whom?) and takes no arguments Only 1 destructor is allowed per class it cannot be overloaded, as it does not take arguments
Destructors class circle private: int xc, yc, radius, ID *ncolour; ~circle () delete ncolour; cout << Deleting circle with ID: << ID << \n ; void set (int x, int y, int r, int circlecolour) xc = x; yc = y; radius = r; *ncolour= circlecolour circle( int x, int y, int r, int id) : xc (x), yc(y), radius(r), ID(id) ncolour = new int; void draw () draw_circle(xc, yc, radius, ncolour); int main() circle c1(15,25,10,1); circle c2(15,15,10,2); cout << -- end ---\n ; --- end --- Deleting circle with ID: 2 Deleting circle with ID: 1
Copy Constructors Take care when a class uses pointers Copy constructor initializes the pointers ending up pointing into the same memory (defined by the old class) When the old class destroys the memory by using the destructor the new class will still have a pointer to that memory. Solution: create its own copy constructor and allocate the memory as required.
Copy constructor class circle private: int xc, yc, radius, ID, *ncolour; ~circle () delete ncolour; cout << Deleting circle with ID: << ID << \n ; int GetColour() return * ncolour ; circle( int x, int y, int r, int id) : xc(x), yc(y), radius(r),id(id) ncolour = new int; void draw () draw_circle(xc, yc, radius, ncolour); circle (circle & tmpcircle ) ncolour = new int; ncolour = tmpcircle.getcolour();
Copy constructor Copy constructor required to use reference parameters, and therefore it will have access to their argument s data The purpose is to make a copy of the argument, no reason the constructor should modify the argument s data Thus, specify the keyword const in the parameter list circle (const circle & tmpcircle )
this pointer The this pointer points to the class object instance by the member function. Hidden object parameter for each member function All member data and member functions can be accessed using the this pointer
this pointer Can be used to compare a particular object with the member function of the object being executed. Can be used to access members that may be hidden by parameters with the same name.
this pointer class circle private: int xc, yc, radius ; circle() : xc(25), yc(25), radius(5) /* empty body */ void set (int xc, int yc, int radius) this->xc = xc; this->yc = yc; this->radius = radius; void get () cout << \Enter x coordinate: ; cin >> this-> xc; cout << \Enter y coordinate: ; cin >> this-> yc; cout << \Enter radius : ; cin >> radius; void draw () draw_circle(xc, yc, radius); No difference between the cin >> this-> xc; and cin >> xc;
Accessibility Private - only within the class Protected - within the class and the derived class Public open (not protected) and accessible from everywhere in the program
Inheritance class grafobject protected: int xc, yc; grafobject() xc(25), yc(25) cout << GRAFOBJECT constructor ; void set (int x, int y) xc = x; yc = y; class circle : public grafobject private: int radius ; circle () radius(5) cout << CIRCLE constructor ; class cannot invoke private members from base class derived base class class Inheritance don t work in reverse. Base class do not know about the members from the classes that are derived from the base class.
Inheritance: Constructor and Destructors class grafobject protected: int xc, yc, ncolour; grafobject():xc(25), yc(25) cout << GRAFOBJECT constructor ; ~grafobject() cout << GRAFOBJECT destructor ; void set (int x, int y) void linecolour (int ncolour) cout << Set GRAFOBJECT colour ; class circle : public grafobject private: int radius ; circle (): radius(5) cout << CIRCLE constructor ; ~circle () cout << CIRCLE destructor ; void draw() void linecolour (int ncolour) cout << Set Circle colour ; int main() circle c1 ; c1.draw(); cout << -- end ---\n ; GRAFOBJECT constructor CIRCLE constructor --- end --- CIRCLE destructor GRAFOBJECT destructor
Derived class constructor class grafobject protected: int xc, yc; grafobject() : xc(15), yc(15) grafobject(int x, int y) : xc(x), yc(y) class circle : public grafobject privat: int radius; circle() : grafobject() radius = 0; Overloaded constructors in the base class impose overloaded constructors in the derived class Calling constructor from the initialization list. circle (int x, int y, int r) : grafobject(x,y) radius = r;
Calling the base method from overridden method class grafobject protected: int xc, yc, ncolour; grafobject():xc(25), yc(25) cout << GRAFOBJECT constructor ; ~grafobject() cout << GRAFOBJECT destructor ; void set (int x, int y) void setlinecolour (int ncolour) cout << Set GRAFOBJECT colour ; class circle : public grafobject private: int radius ; circle (): radius(5) cout << CIRCLE constructor ; ~circle () cout << CIRCLE destructor ; void draw() void setlinecolour (int ncolour) cout << Set Circle colour ; Override (overwrite): crate a method in a derived class that has the same name and the same signature as the method in the base class. int main() circle c1; c1.setlinecolour(255); c1.draw(); c1.grafobject::setlinecolour(125); cout << --- end ---\n ;
Pointers to member function class Base void show() cout << Show Base class ; class Derived1 : public Base void show() cout << Show Derived 1 class ; class Derived2 : public Base void show() cout << Show Derived 2 class ; int main() Derived1 d1; Derived2 d2; Base *pobj pobj = & d1; *pobj->show(); pobj = & d2; *pobj->show(); Show Base class Show Base class Compiler does not complain because the member functions are type-compatible and selects the function that matches the type.
Virtual Functions Used to override member functions Calling a function in one class may call a function in another class Enables an execution of different functions by using the same function name - POLIMORPHYSMUS
Virtual Functions class Base virtual void show() cout << Show Base class ; class Derived1 : public Base void show() cout << Show Derived 1 class ; class Derived2 : public Base void show() cout << Show Derived 2 class ; int main() Derived1 d1; Derived2 d2; Base *pobj pobj = & d1; *pobj->show(); pobj = & d2; *pobj->show(); Show Derived 1 class Show Derived 2 class Compiler selects the function that matches the content (and not only the type)
Virtual Destructors Usually destructors are used to free memory (delete) If destructor is not declared virtual - only the memory of the base class is destroyed Base class destructors should be virtual The destructors of the derived class are called
Non-Virtual Destructors class Base virtual void show() cout << Show Base class ; ~Base () cout << Base destroyed ; class Derived1 : public Base void show() cout << Show Derived 1 class ; ~ Derived1 () cout << Derived 1 destroyed ; int main() Base *pbase = new Derived delete pbase ; return 0; Base destroyed
Virtual Destructors class Base virtual void show() cout << Show Base class ; virtual ~Base () cout << Base destroyed ; class Derived1 : public Base void show() cout << Show Derived 1 class ; ~ Derived1 () cout << Derived 1 destroyed ; int main() Base *pbase = new Derived delete pbase ; return 0; Derived 1 destroyed Base destroyed
Literature for further reading: Object-oriented programming in C++ Robert Lafore Teach yourself C++ in 21 Days Jasse Liberty C++ Master Class Andre Willms