Presentation is loading. Please wait.

Presentation is loading. Please wait.

Before Introducing Inheritance … Here is another way to re-use what have been developed: This is known as the object composition! A real-world example.

Similar presentations


Presentation on theme: "Before Introducing Inheritance … Here is another way to re-use what have been developed: This is known as the object composition! A real-world example."— Presentation transcript:

1 Before Introducing Inheritance … Here is another way to re-use what have been developed: This is known as the object composition! A real-world example of composition may be seen in the relation of an automobile to its parts.

2 How to generate complex object type from a number of basic types? This is known as the object composition! class Point { private: float x, y; }; class Edge { private: Point vertex1, vertex2 }; class Triangle{ public: private: Point vertex1, vertex2, vertex3; Edge edge1, edge2, edge3; };

3 How to initialize the composite objects? This is known as the object composition! class Point { private: float x, y; }; class Edge { public: Edge (const Point &p1, const Point &p2) : vertex1(p1), vertex2(p2) {…} private: Point vertex1, vertex2; }; class Triangle{ …… };

4 What if the composite class is defined as follows? class Point { private: float x, y; }; class Edge { private: Point vertex1, vertex2; }; class Polygon{ public: private: Point *vertices; Edge *edges; int nvertices, nedges; };

5 Inheritance and Derived Classes

6 Why do we need it? – It is one of the most powerful mechanisms offered by OOP. – It enables potentially infinite reuse of resources. – It can be used to enhance and improve the previous programs for the changing requirements. – It also matches what we know about the real- world.

7 An Example (from textbook) Consider the employees of a company. All of them have some common attributes, like SSN, name, employeeID, netPay, etc. But they may be paid differently. Some are paid hourly, while the others may be paid with a fixed wage (weekly/monthly) If we use two different classes to represent these two groups of employees who are paid differently, each of these classes will need to define those common attributes listed above. This is not very efficient in terms of coding. This situation can be more dramatic in the real cases of software development.

8 An Example (from textbook) Consider the employees of a company. All of them have some common attributes, like SSN, name, employeeID, netPay, etc. But they may be paid differently. Some are paid hourly, while the other may be paid with a fixed wage (weekly/monthly) To address that, we use the inheritance!

9 An Example (from textbook) #include using std::string; class Employee { public: // constructor list // member functions private: string name; string ssn; double netPay; }; We first define a class to implement the common properties and behaviors of all employees.

10 An Example (from textbook) #include using std::string; class Employee { public: // constructor list // member functions private: string name; string ssn; double netPay; }; Next, we define a new class to *inherit* these common attributes and behaviors. class HourlyEmployee : public Employee { public: // constructor list // new member functions private: double wageRate; double hours; };

11 An Example (from textbook) #include using std::string; class Employee { public: // constructor list // member functions private: string name; string ssn; double netPay; }; Next, we define a new class to *inherit* these common attributes and behaviors. Base class or parent class derived class or child class class HourlyEmployee : public Employee { public: // constructor list // new member functions private: double wageRate; double hours; }; In other words, we create a new class *based on* an existing class

12 How to use inheritance From this example, we see the inheritance is achieved in the following format class DerivedClass : public BaseClass { }; From this example, we can also learn that the base class typically provides a *general* definition (for all objects), while the individual child classes provide more *specific* definition (sub-sets of the objects).

13 How to use inheritance class DerivedClass : public BaseClass { }; This inheritance can be carried on during the development of the program, and eventually we obtain an inheritance relation of the classes much similar to a family tree. A BC D E …… To represent this inheritance relation between classes and other relations including friend relationship, we will use UML!

14 What benefits can inheritance provide? Derived class *inherits* all the member variables and functions except the constructors of the base class. So what do you think is the benefit here? Derived class can define its own and new members that are for its specific purpose! AB

15 More on Inheritance Derived class can *overwrite (or re-define)* the inherited member functions from the base class. This will NOT affect the previous definition in the base class. Derived class can NOT change the types of the inherited member variables. Again, derived class does NOT inherit the private members of the base class and its constructors. class DerivedClass : public BaseClass {} class DerivedClass : private BaseClass {} We typically use public access to inherit base class. “private” or “protected” inheritance is possible, but seldom used. All members of the base class are now private to the derived class!

16 CORRECTION! Derived class *inherits* all the public member variables and functions except the constructors of the base class. Derived class DOES NOT inherits all the private member variables and functions of the base class. So what do you think is the benefit here? Derived class can define its own and new members that are for its specific purpose! Correction: the memory allocated for the derived object contains everything from the base class including its private members! But you cannot directly access that! AB

17 CORRECTION! Derived class *inherits* all the member variables and functions except the constructors and destructor of the base class. So what do you think is the benefit here? Derived class can define its own and new members that are for its specific purpose! Correction: the memory allocated for the derived object contains everything from the base class including its private members! But you cannot directly access that! AB Derived class "inherits" private member variables - But still cannot directly access them, not even in the member function of the derived class.

18 class my_emp{ public: my_emp() { name = NULL; age = 0; salary = 0.0; } my_emp(char *in_name, int in_age, float in_salary):salary(in_salary), age(in_age) { name = new char[strlen(in_name)+1]; strcpy(name, in_name); } ~my_emp() { delete [] name; } void print_name() const { cout << "This is " << name << endl;} int get_age () const { return age; } float get_salary() const { return salary; } private: char *name; int age; float salary; }; class manager : public my_emp { public: manager(char *in_name, short in_age, float in_salary, int in_level) : my_emp(in_name, in_age, in_salary) { level=in_level; } void print_level() { cout << "level: " << level << endl; cout<<“age: "<<age<<endl; //ILLEGAL! } private: int level; }; void main() { manager m ("Chen", 0, 0, 1); m.age = 25; //ILLEGAL! m.salary = 1000000; //ILLEGAL! m.print_level(); m.print_name(); }

19 class my_emp{ public: my_emp() { name = NULL; age = 0; salary = 0.0; } my_emp(char *in_name, int in_age, float in_salary):salary(in_salary), age(in_age) { name = new char[strlen(in_name)+1]; strcpy(name, in_name); } ~my_emp() { delete [] name; } void print_name() const { cout << "This is " << name << endl;} int get_age () const { return age; } float get_salary() const { return salary; } private: char *name; int age; float salary; }; class manager : public my_emp { public: manager(char *in_name, short in_age, float in_salary, int in_level) : my_emp(in_name, in_age, in_salary) { level=in_level; } void print_level() { cout << "level: " << level << endl; } private: int level; }; void main() { manager m ("Chen", 0, 0, 1); m.print_level(); m.print_name(); } What is the output?

20 class my_emp{ public: my_emp() { name = NULL; age = 0; salary = 0.0; } my_emp(char *in_name, int in_age, float in_salary):salary(in_salary), age(in_age) { name = new char[strlen(in_name)+1]; strcpy(name, in_name); } ~my_emp() { delete [] name; } void print_name() const { cout << "This is " << name << endl;} int get_age () const { return age; } float get_salary() const { return salary; } private: char *name; int age; float salary; }; class manager : public my_emp { public: manager(char *in_name, short in_age, float in_salary, int in_level) : my_emp(in_name, in_age, in_salary) { level=in_level; } void print_level() { cout << "level: " << level << endl; } private: int level; }; void main() { manager m ("Chen", 0, 0, 1); m.print_level(); m.print_name(); } level: 1 This is Chen

21 class my_emp{ public: my_emp() { name = NULL; age = 0; salary = 0.0; } my_emp(char *in_name, int in_age, float in_salary):salary(in_salary), age(in_age) { name = new char[strlen(in_name)+1]; strcpy(name, in_name); } ~my_emp() { delete [] name; } void print_name() const { cout << "This is " << name << endl;} int get_age () const { return age; } float get_salary() const { return salary; } private: char *name; int age; float salary; }; class manager : private my_emp { public: manager(char *in_name, short in_age, float in_salary, int in_level) : my_emp(in_name, in_age, in_salary) { level=in_level; } void print_level() { cout << "level: " << level << endl; } private: int level; }; void main() { manager m ("Chen", 0, 0, 1); m.print_level(); m.print_name(); } How about now?

22 class my_emp{ public: my_emp() { name = NULL; age = 0; salary = 0.0; } my_emp(char *in_name, int in_age, float in_salary):salary(in_salary), age(in_age) { name = new char[strlen(in_name)+1]; strcpy(name, in_name); } ~my_emp() { delete [] name; } void print_name() const { cout << "This is " << name << endl;} int get_age () const { return age; } float get_salary() const { return salary; } private: char *name; int age; float salary; }; class manager : private my_emp { public: manager(char *in_name, short in_age, float in_salary, int in_level) : my_emp(in_name, in_age, in_salary) { level=in_level; } void print_level() { cout << "level: " << level << endl; } private: int level; }; void main() { manager m ("Chen", 0, 0, 1); m.print_level(); m.print_name(); //ILLEGAL! } How about now?

23 class my_emp{ public: my_emp() { name = NULL; age = 0; salary = 0.0; } my_emp(char *in_name, int in_age, float in_salary):salary(in_salary), age(in_age) { name = new char[strlen(in_name)+1]; strcpy(name, in_name); } ~my_emp() { delete [] name; } void print_name() const { cout << "This is " << name << endl;} int get_age () const { return age; } float get_salary() const { return salary; } private: char *name; int age; float salary; }; class manager : private my_emp { public: manager(char *in_name, short in_age, float in_salary, int in_level) : my_emp(in_name, in_age, in_salary) { level=in_level; } void print_level() { cout << "level: " << level << endl; pirnt_name(); // Call it here! } private: int level; }; void main() { manager m ("Chen", 0, 0, 1); m.print_level(); } To get the same output

24 The protected: Qualifier New classification of class members Allows access "by name" in derived class – But nowhere else – Still no access "by name" in other classes In class it’s defined  acts like private Considered "protected" in derived class – To allow future derivations

25 class my_emp{ public: my_emp() { name = NULL; age = 0; salary = 0.0; } my_emp(char *in_name, int in_age, float in_salary):salary(in_salary), age(in_age) { name = new char[strlen(in_name)+1]; strcpy(name, in_name); } ~my_emp() { delete [] name; } void print_name() const { cout << "This is " << name << endl;} int get_age () const { return age; } float get_salary() const { return salary; } protected: char *name; int age; float salary; }; class manager : public my_emp { public: manager(char *in_name, short in_age, float in_salary, int in_level) : my_emp(in_name, in_age, in_salary) { level=in_level; } void print_level() { cout << "level: " << level << endl; cout << “age: " << age << endl; //OK } private: int level; }; void main() { manager m ("Chen", 0, 0, 1); m.age = 25; //ILLEGAL! m.salary = 1000000; //ILLEGAL! m.print_level(); m.print_name(); }

26 Only member functions of the same class private protected Member functions of the same class and the derived class public Every one !

27 Constructor of Derived Class class DerivedClass : public BaseClass {… public: DerivedClass (argument list) : BaseClass (argument list) { } … }; class DerivedClass : public BaseClass {… public: DerivedClass (argument list) { } … }; Or In the initialization section

28 class my_emp{ public: my_emp() { name = NULL; age = 0; salary = 0.0; } my_emp(char *in_name, int in_age, float in_salary):salary(in_salary), age(in_age) { name = new char[strlen(in_name)+1]; strcpy(name, in_name); } ~my_emp() { delete [] name; } void print_name() const { cout << "This is " << name << endl;} int get_age () const { return age; } float get_salary() const { return salary; } protected: char *name; int age; float salary; }; class manager : public my_emp { public: manager(char *in_name, short in_age, float in_salary, int in_level) : my_emp(in_name, in_age, in_salary) { level=in_level; } void print_level() { cout << "level: " << level << endl; cout << “age: " << age << endl; //OK } private: int level; }; void main() { manager m ("Chen", 0, 0, 1); m.print_level(); m.print_name(); }

29 The order of constructor calling In general, First, the constructor of the base class Second, the constructor of the object type of member variables Finally, the constructor of the derived class class DerivedClass : public BaseClass {… public: DerivedClass (argument list) : BaseClass (argument list), A (initial value) { } … private: A obj; //A is a pre-defined class! };

30 class my_emp{ public: my_emp() { name = NULL; age = 0; salary = 0.0; } my_emp(char *in_name, int in_age, float in_salary):salary(in_salary), age(in_age) { name = new char[strlen(in_name)+1]; strcpy(name, in_name); } ~my_emp() { delete [] name; } void print_name() const { cout << "This is " << name << endl;} int get_age () const { return age; } float get_salary() const { return salary; } protected: char *name; int age; float salary; }; class manager : public my_emp { public: manager(char *in_name, short in_age, float in_salary, int in_level) : my_emp(in_name, in_age, in_salary), level(in_level) { } void print_level() { cout << "level: " << level << endl; cout << “age: " << age << endl; //OK } private: int level; }; void main() { manager m ("Chen", 0, 0, 1); m.print_level(); m.print_name(); }

31 The order of the constructor calling and destructor calling for a derived object B C A class A { }; class B : public A { }; class C : public B { }; C obj_c; when create an object of C it will call the constructors in the order of A→B →C when the program (or function) is exiting it will call the destructors in the order of C→B →A

32 Redefinition class BaseClass { public: … void method1(argument list){//implementation in base class} }; class DerivedClass : public BaseClass {… public: void method1(same argument list!) {//new implementation } void method1(different argument list) {//new implementation } … };

33 Redefinition How to call the member functions of the base class that are re-defined. class BaseClass { public: … void method1(argument list){//implementation in base class} }; class DerivedClass : public BaseClass {… public: void method1(same argument list!) {//new implementation } … }; DerivedClass obj1; obj1.BaseClass::method1(input parameters);

34 Multiple Inheritance The new derived class can inherit from more than one base class class A { …… }; class B { …… }; class C : public A, public B { …… }; Like single inheritance, the derived class will automatically inherit all the public members from all its parent classes.

35 Multiple Inheritance The new derived class can inherit from more than one base class class A { …… }; class B { …… }; class C : public A, public B { …… public: C (argument list) : A(arguments), B(arguments) {…} }; Like single inheritance, the derived class will automatically inherit all the public members from all its parent classes. Be careful about the constructor

36 Multiple Inheritance Problem of multiple inheritance class A { …… public: int val; }; class C : public A, public B { …… }; C c_obj; c_obj.val=0; // which “val”, from A or from B? Ambiguity of inherited members! class B { …… public: int val; };

37 Multiple Inheritance Problem of multiple inheritance class A { …… public: int val; }; class C : public A, public B { …… }; C c_obj; c_obj.A::val=0; // legal c_obj.B::val=2; // legal as well Solution – use scope resolution “::” class B { …… public: int val; };

38 Overall, try to avoid multiple inheritance, as you may not know the ancestors of those base classes. The configuration to the right could happen! A BC D A class A { public: void vf() { cout<<"I come from class A"<<endl;} }; class B: public A{}; class C: public A{}; class D: public B, public C{}; void main() { D d; d.vf ();// error, multiple copies of vf() }

39 There is indeed one possible solution to address that i.e. using virtual inheritance A BC D A class A { public: void vf() { cout<<"I come from class A"<<endl;} }; class B: virtual public A{}; class C: virtual public A{}; class D: public B, public C{}; void main() { D d; d.vf ();// this OK now }

40 Another more complicated example class B1:virtual public B,virtual public A{ public: B1(int i){ cout<<"Constructing B1"<<endl; } }; class B2: public A, virtual public B { public: B2(int j){ cout<<"Constructing B2"<<endl; } }; class D: public B1, public B2 { public: D(int m,int n): B1(m),B2(n){ cout<<"Constructing D"<<endl; } A a; }; void main(){ D d(1,2); }


Download ppt "Before Introducing Inheritance … Here is another way to re-use what have been developed: This is known as the object composition! A real-world example."

Similar presentations


Ads by Google