Constructors and destructors 1 1 Department of Computer Science Poznan University of Technology 2012.10.07 / OOP Laboratory
Outline 1 2 3 4 5
Outline 1 2 3 4 5
Outline 1 2 3 4 5
Outline 1 2 3 4 5
Outline 1 2 3 4 5
Constructor syntax Header file 1 //... 2 class ClassName { 3 public: 4 ClassName(); 5 //... 6 }; 7 //... Code file 1 // other libraries header files... 2 #include "header-file.h" 3 4 ClassName::ClassName() { 5 //... 6 }
Destructor syntax Header file 1 //... 2 class ClassName { 3 public: 4 ~ClassName(); 5 //... 6 }; 7 //... Code file 1 // other libraries header files... 2 #include "header-file.h" 3 4 ClassName::~ClassName() { 5 //... 6 }
Task Analyze and answer questions 1 Which from the constructions below triggers parameterless constructor and destructor invocation and which possibly causes syntax error, comment this(these) line(lines). 1 void myfunction1(classname param) { 25 if (true) { 2 //... 26 ClassName &o6 = o1; 3 } 27 } 4 void myfunction2(classname ¶m) { 28 if (true) { 5 //... 29 ClassName *o7; 6 } 30 } 7 //... 31 if (true) { 8 ClassName o1; 32 ClassName *o8 = o1; 9 myfunction1(o1); 33 } 10 myfunction2(o1); 34 if (true) { 11 if (true) { 35 ClassName *o9 = &o1; 12 ClassName o2; 36 } 13 o2 = o1; 37 if (true) { 14 } 38 ClassName *o10 = new ClassName; 15 if (true) { 39 } 16 ClassName o3 = ClassName(); 40 if (true) { 17 } 41 ClassName o11(); 18 if (true) { 42 delete o11; 19 ClassName o4; 43 } 20 o4 = ClassName(); 44 if (true) { 21 } 45 ClassName *o12 = new ClassName(); 22 if (true) { 46 delete o12; 23 ClassName o5 = o1; 47 } 24 } Use cout in your constructor and make use of static/global variable lineno to determine in which line constructor/destructor was invoked.
syntax Header file 1 //... 2 class ClassName { 3 // <access-modifier> 4 ClassName([const ]type [&]param1name[, type param2name = defaultvalue[,...]]); 5 // the ampersand (passing value by reference) is needed 6 // in copy constructor of the same type! 7 // possible other parameters than the first one 8 // must have assigned default value! 9 }; 10 //... Code file 1 //... 2 #include "class_name.h" 3 //... 4 ClassName::ClassName([const ]type [&]paramname[, type param2name = defaultvalue[,...]]) { 5 // the ampersand (passing value by reference) is needed 6 // in copy constructor of the same type! 7 //... 8 } 9 //...
usage is invoke in two cases 1 While initializing the variable, e.g: 1 ClassName cn = valuetocopy; // valuetocopy not necessairly have to be of type ClassName But not: 1 ClassName cn; 2 cn = valuetocopy; 2 While passing to the function/method, e.g.: 1 void myfunction(classname cn) { 2 //... 3 } 4 //... 5 myfunction(valuetocopy); // valuetocopy not necessairly have to be of type ClassName
Tasks Analyze and answer questions Analyze task code from the section with parameterless constructors and destructors and answer which from given lines cause triggering copy constructor.
declaration syntax Header file 1 //... 2 class ClassName { 3 // <access-modifier> 4 [explicit ]ClassName(type paramname[=defaultvalue[,...]]); 5 // explicit keyword prevents constructor from being interpreted as 6 // a copy constructor 7 }; Code file 1 //... 2 #include "class_name.h" 3 //... 4 ClassName::ClassName(type paramname[=defaultvalue[,...]]) { 5 //... 6 }
usage Note Once you declare any constructor with parameter the default parameterless constructor (the one generated by the compiler if no constructors are explicitly declared) will vanish, so you won t be able e.g. to declare object like this: 1 ClassName cn; Neither to inherit from the class without explicitly define constructor inheritance. Of course unless you define the parameterless constructor.
Tasks Complete the tasks 1 Create class Product with constructor taking as argument product name and its price. Create the static field aggregating prices upon instances of Product class. Each time you create the Product instance aggregate should sum its price. Similarly when the object will be destroyed its price should be subtracted. 2 Create class String with a parameterless constructor as well as copy constructor taking const char* variable as an argument that constructor should copy in case of its removal before the object destruction. Class should also be equipped with copy constructor taking a single argument of type integer, character and double value. Create an virtual method tostring that returns containing String. Remember to free the memory that was allocated in the constructor! To parse integer, char and double argument use sprintf function of stdio.h library.
About About The virtual destructor protects the program from the leak of the memory in case of usage of explicit destructors (delete) when object is treated as one of its base class. There is no such problem in case of instances created in place (to construct the object one have not used the new operator) because the type of the instance is exactly as in variable definition. 1 //... 2 class BaseClass { 3 ~BaseClass(); 4 }; 5 //... 6 class ChildClass: public BaseClass { 7 ~ChildClass(); 8 }; 9 //... 10 BaseClass *bs = new ChildClass; 11 delete bs; // BaseClass destructor will be invoked though bs points to the ChildClass!!!! Declaration syntax Just like in case of virtual methods virtual keyword should precede the destructor declaration in header file.
Task Complete the task 1 Create class Name inheriting from String class from the previous tasks. Prepare the constructor taking the first and the last name as arguments. Equip the class also with two separate setters for first name and the last name. Store the first and last name in fields of type char *. To store first value you can use derived field from the parent class. Override the tostring method to make it return the char string of format: LastName, FirstName. Use the above code to write the name to the standard output. 1 String *name = new Name("Albert", "Einstein"); 2 printf("%s\n", name->tostring()); 3 delete name; Test whether the last line of the code invokes destructor of the String class or derived Name class.
syntax Header file 1 //... 2 class ClassName [: [modificator] ParentClass] { 3 // <access-modifier> 4 ClassName(); // We can t initialize field without constructor body! 5 //... 6 }; 7 //... Source file 1 #include "class_name.h" 2 3 ClassName(): [ParentConstructor([params]), ] fieldname([constructorparam[,...]]) { 4 // single "constructorparam" can be seen as a default initializing 5 // value in case of primitive types (int, double, char *, etc.) 6 //... 7 }
Tasks Complete following tasks 1 Complete the task 1 from s section. This time use apart from inheriting from String class use two instances of String class to store the first and last name. Initialize the fields in the constructor. 2 (*) Once again complete the same task. In this approach instead of two fields of type String where you d store the first and last name try to inherit multiple times from the String class. You cannot derive directly from the same class two times. You need to create two dumb classes. The question is how to access (assumed) protected field that contain actual char string.