C++: Composition, Aggregation and Polymorphism Jussi Pohjolainen TAMK University of Applied Sciences
Inheritance Inheritance is a relationship between two or more classes where derived class inherites behaviour and attributes of pre-existing (base) classes Intended to help  reuse  of existing code with little or no modification
Basic example Programmer inherites all the methods and attributes from Human Human string name void sleep() void drink() void eat() Programmer int salary void implementApps() void beNerd()
Abstract Class Abstract class is a class which you cannot instantiate (create objects) You can inherit abstract class and create objects from the inherited class, if it is concrete one Abstract class in C++ has abstract methods, that do not have implementations These methods forces derived classes to implement those methods
Example <<abstract>> Mammal string name void makesound() {abstract} Elephant int trunkLength makesound()
COMPOSITION AND AGGREGATION
Composition Relatioship between objects, where one object owns, or  has  the other object Car  has or owns  Motor When Car is build, it's motor is built also When Car is destroyed it's motor is destroyed
UML notation
C++: Composition // Composition class Car { private: Motor* motor; public:  Car()  { motor = new Motor(); } ~Car() { delete motor; } };
Aggregation In composition, when the owning object is destroyed, so are the contained objects In  aggregation  this is not neccessarily true Aggregation is a form of composition, where contained objects can still &quot;live&quot; after the owning object is released Departments has professors, if department is closed, professors still live...
UML Notation
C++: Simple Aggregation // Aggregation class Deparment { private: Professor* professor; public:  Department(Professor* prof) : professor(prof) { } ~Department() { } };
One to Many?
C++: One to Many class Department { private: Professor* members[20]; int numberOfMembers; public:  Department(Professor* prof) {  members[0] = prof; numberOfMembers = 1; } void addProfessor(Professor* prof) { members[numberOfMembers] = prof; numberOfMembers++; } ~Department() { } };
VECTOR: DYNAMIC ARRAY
One to  Many? In the previous code example department had 1 – 20 professors What if we do not want to specify the maximum number? What if we want that the deparment has 1 – x professors and the number can be determined during runtime?
Vector Vector is just like an array... ...But it is  dynamic array This means that it can  grow dynamically You do not have to specify the size for the array Vector is  a class from c++ standard library , just like string #include <vector>
Vector Possibilities Add and remove elements Iterate the elements Access individual elements
Simple Example vector<int> numberArray; int a = 1; int b = 2; int c = 3; numberArray.push_back(1); numberArray.push_back(2); numberArray.push_back(3); for( int i=0; i < numberArray.size(); i++ )  { cout << numberArray.at(i) << endl; }
When the elements are created dynamically vector< int* > numberArray;  int* a = new int(1); int* b = new int(2); int* c = new int(3);  numberArray.push_back(a); numberArray.push_back(b); numberArray.push_back(c); for(int i=0; i<numberArray.size(); i++)  cout << *numberArray.at(i) << endl; for(int i=0; i<numberArray.size(); i++)  delete numberArray.at(i);
When the elements are created dynamically – part 2 vector<int*> numberArray;  numberArray.push_back(new int(1)); numberArray.push_back(new int(2)); numberArray.push_back(new int(3)); for(int i=0; i<numberArray.size(); i++)  cout << *numberArray.at(i) << endl; for(int i=0; i<numberArray.size(); i++)  delete numberArray.at(i);
When vector is created dynamically vector<int>* numberArray = new vector<int>(); numberArray->push_back(1); numberArray->push_back(2); numberArray->push_back(3); for(int i=0; i<numberArray->size(); i++)  { cout << numberArray->at(i) << endl; } delete numberArray;
vector and elements dynamically vector<int*>* numberArray = new vector<int*>(); numberArray->push_back( new int(1) ); numberArray->push_back( new int(2) ); numberArray->push_back( new int(3) ); for(int i=0; i<numberArray->size(); i++)  cout << *numberArray->at(i) << endl; for(int i=0; i<numberArray->size(); i++)  delete numberArray->at(i); delete numberArray;
vector methods size operator[] push_back pop_back insert erase swap See: http://www.cplusplus.com/reference/stl/vector/
C++: One to Many class Department { private: vector<Professor*>* members; public:  Department(Professor* prof) {  members = new Vector<Professor*>(); members->push_back(prof); } void addProfessor(Professor* prof) { members->push_back(prof); } ~Department() { delete members; } };
POLYMORPHISM
Introduction to Polymorphism // This creates a pointer a, which has a memory address Dog* a; // This creates a new object to dynamic memory and returns memory address of the object, which is stored in a a = new Dog();
Class Diagram
Pointer Type differs from Object Type? // This creates a pointer a, which has a memory address Mammal* a; // This creates a new object to dynamic memory and returns memory address of the object, which is stored in a a = new Dog();
Pointer type vs. Object type When declaring a new Pointer Mammal* pointer; This pointer can have reference to Mammal and all of it's derived classes! So this is acceptible: Mammal* pointer = new Mammal(); Mammal* pointer = new Dog(); Mammal* pointer = new Human(); Mammal* pointer = new Cat();
C++ #include <iostream> using namespace std; class Mammal { }; class Human : public Mammal { }; class Dog  : public Mammal { }; class Cat  : public Mammal { }; int main()  { Mammal* pointer1 = new Mammal(); Mammal* pointer2 = new Human(); Mammal* pointer3 = new Dog(); Mammal* pointer4 = new Cat(); // and remember to delete above: delete pointer1; delete ...
Array class Mammal { }; class Human : public Mammal { }; class Dog  : public Mammal { }; class Cat  : public Mammal { }; int main()  { Mammal array[2]; Dog musti; Human pekka; array[0] = musti; array[1] = pekka; return 0; }
vector class Mammal { }; class Human : public Mammal { }; class Dog  : public Mammal { }; class Cat  : public Mammal { }; int main()  { vector<Mammal> dynamicArray; Dog musti; Human pekka; dynamicArray.push_back(musti); dynamicArray.push_back(pekka); return 0; }
vector: Everything into dynamic memory vector<Mammal*>* dynamicArray = new vector<Mammal*>(); dynamicArray->push_back( new Dog() ); dynamicArray->push_back( new Human() ); dynamicArray->push_back( new Mammal() ); dynamicArray->push_back( new Cat() ); for(int i=0; i < dynamicArray->size(); i++) delete dynamicArray->at(i); delete dynamicArray;
Problem? void function(Mammal* m) { // m may hold Dog, Cat or // Human.. m->Bark(); }
Casting void function(Mammal* m) { Dog* dog =  dynamic_cast<Dog*>(m); dog->Bark(); }
Type info #include <typeinfo> void function(Mammal* m) { Dog* temp = new Dog(); if(typeid(*temp) == typeid(*m)) { delete temp; Dog* dog=  dynamic_cast<Dog*>(m); dog->Bark(); } }
Class Diagram
Zoo-example class Zoo { private: vector<Animal*>* animals; public:  Zoo() {  animals = new Vector<Animal*>(); } void addAnimal(Animal* animal) { animals->push_back(animal); } ~Zoo() { delete animals; } };
Inheritance Example (1/2) class Mammal {  protected: string name_; public: void SetName(string name) { name_ = name; } }; class Human : public Mammal { }; class Dog  : public Mammal { }; class Cat  : public Mammal { };
Inheritance Example (2/2) int main()  { Human pekka; pekka.SetName(&quot;Pekka&quot;); Dog musti; musti.SetName(&quot;Musti&quot;); return 0; }
Class Diagram
C++ class Mammal {  protected: string name_; public: void SetName(string name) { name_ = name; } void PrintInformation() { cout << &quot;Hello, I'm mammal and my name is &quot; << name_ << endl; } }; class Human : public Mammal {  public:  void PrintInformation() { cout << &quot;Hello, I'm human and my name is &quot; << name_ << endl; } };
C++ int main()  { Human* pekka = new Human(); pekka->SetName(&quot;Pekka&quot;); // prints // Hello, I'm human and my name is Pekka pekka->PrintInformation(); delete pekka;  return 0; }
What about now? int main()  { Mammal* pekka = new Human(); pekka->SetName(&quot;Pekka&quot;); // prints // Hello, I'm  mammal  and my name is Pekka pekka->PrintInformation(); delete pekka return 0; }
Fix class Mammal {  protected: string name_; public: void SetName(string name) { name_ = name; } virtual  void PrintInformation() { cout << &quot;Hello, I'm mammal and my name is &quot; << name_ << endl; } }; class Human : public Mammal {  public:  void PrintInformation() { cout << &quot;Hello, I'm human and my name is &quot; << name_ << endl; } };
What about now? int main()  { Mammal* pekka = new Human(); pekka->SetName(&quot;Pekka&quot;); // prints // Hello, I'm  human  and my name is Pekka pekka->PrintInformation(); delete pekka return 0; }
Without Virtual A* p1 = new A(); p1->method(); B* p2 = new B(); p2->method(); A* p3 = new B(); p3->method();
With Virtual A* p1 = new A(); p1->method(); B* p2 = new B(); p2->method(); A* p3 = new B(); p3->method();
Virtual in Destructors class Mammal {  public: Mammal() { cout << &quot;Mammal Constructor\n&quot;; } ~Mammal() { cout << &quot;Mammal Destructor\n&quot;; }  }; class Human : public Mammal {  public: Human() { cout << &quot;Human Constructor\n&quot;; } ~Human() { cout << &quot;Human Destructor\n&quot;; }  }; Mammal* pekka = new Human(); delete pekka; Result: Mammal Constructor Human Constructor Mammal Destructor
Virtual in Destructors class Mammal {  public: Mammal() { cout << &quot;Mammal Constructor\n&quot;; } virtual  ~Mammal() { cout << &quot;Mammal Destructor\n&quot;; }  }; class Human : public Mammal {  public: Human() { cout << &quot;Human Constructor\n&quot;; } ~Human() { cout << &quot;Human Destructor\n&quot;; }  }; Mammal* pekka = new Human(); delete pekka; Result: Mammal Constructor Human Constructor Human Destructor Mammal Destructor
Problem class Vehicle { }; class Motor { }; class Car : public Vehicle { private: Motor* motor; public: Car() { motor = new Motor(); } ~Car() { delete motor; } }; int main()  { Vehicle* datsun = new Car(); delete datsun;  return 0; }
Solution class Vehicle { public: virtual ~Vehicle() { } }; class Motor { }; class Car : public Vehicle { private: Motor* motor; public: Car() { motor = new Motor(); } ~Car() { delete motor; } }; int main()  { Vehicle* datsun = new Car(); delete datsun;  return 0; }

C++: inheritance, composition, polymorphism

  • 1.
    C++: Composition, Aggregationand Polymorphism Jussi Pohjolainen TAMK University of Applied Sciences
  • 2.
    Inheritance Inheritance isa relationship between two or more classes where derived class inherites behaviour and attributes of pre-existing (base) classes Intended to help reuse of existing code with little or no modification
  • 3.
    Basic example Programmerinherites all the methods and attributes from Human Human string name void sleep() void drink() void eat() Programmer int salary void implementApps() void beNerd()
  • 4.
    Abstract Class Abstractclass is a class which you cannot instantiate (create objects) You can inherit abstract class and create objects from the inherited class, if it is concrete one Abstract class in C++ has abstract methods, that do not have implementations These methods forces derived classes to implement those methods
  • 5.
    Example <<abstract>> Mammalstring name void makesound() {abstract} Elephant int trunkLength makesound()
  • 6.
  • 7.
    Composition Relatioship betweenobjects, where one object owns, or has the other object Car has or owns Motor When Car is build, it's motor is built also When Car is destroyed it's motor is destroyed
  • 8.
  • 9.
    C++: Composition //Composition class Car { private: Motor* motor; public: Car() { motor = new Motor(); } ~Car() { delete motor; } };
  • 10.
    Aggregation In composition,when the owning object is destroyed, so are the contained objects In aggregation this is not neccessarily true Aggregation is a form of composition, where contained objects can still &quot;live&quot; after the owning object is released Departments has professors, if department is closed, professors still live...
  • 11.
  • 12.
    C++: Simple Aggregation// Aggregation class Deparment { private: Professor* professor; public: Department(Professor* prof) : professor(prof) { } ~Department() { } };
  • 13.
  • 14.
    C++: One toMany class Department { private: Professor* members[20]; int numberOfMembers; public: Department(Professor* prof) { members[0] = prof; numberOfMembers = 1; } void addProfessor(Professor* prof) { members[numberOfMembers] = prof; numberOfMembers++; } ~Department() { } };
  • 15.
  • 16.
    One to Many? In the previous code example department had 1 – 20 professors What if we do not want to specify the maximum number? What if we want that the deparment has 1 – x professors and the number can be determined during runtime?
  • 17.
    Vector Vector isjust like an array... ...But it is dynamic array This means that it can grow dynamically You do not have to specify the size for the array Vector is a class from c++ standard library , just like string #include <vector>
  • 18.
    Vector Possibilities Addand remove elements Iterate the elements Access individual elements
  • 19.
    Simple Example vector<int>numberArray; int a = 1; int b = 2; int c = 3; numberArray.push_back(1); numberArray.push_back(2); numberArray.push_back(3); for( int i=0; i < numberArray.size(); i++ ) { cout << numberArray.at(i) << endl; }
  • 20.
    When the elementsare created dynamically vector< int* > numberArray; int* a = new int(1); int* b = new int(2); int* c = new int(3); numberArray.push_back(a); numberArray.push_back(b); numberArray.push_back(c); for(int i=0; i<numberArray.size(); i++) cout << *numberArray.at(i) << endl; for(int i=0; i<numberArray.size(); i++) delete numberArray.at(i);
  • 21.
    When the elementsare created dynamically – part 2 vector<int*> numberArray; numberArray.push_back(new int(1)); numberArray.push_back(new int(2)); numberArray.push_back(new int(3)); for(int i=0; i<numberArray.size(); i++) cout << *numberArray.at(i) << endl; for(int i=0; i<numberArray.size(); i++) delete numberArray.at(i);
  • 22.
    When vector iscreated dynamically vector<int>* numberArray = new vector<int>(); numberArray->push_back(1); numberArray->push_back(2); numberArray->push_back(3); for(int i=0; i<numberArray->size(); i++) { cout << numberArray->at(i) << endl; } delete numberArray;
  • 23.
    vector and elementsdynamically vector<int*>* numberArray = new vector<int*>(); numberArray->push_back( new int(1) ); numberArray->push_back( new int(2) ); numberArray->push_back( new int(3) ); for(int i=0; i<numberArray->size(); i++) cout << *numberArray->at(i) << endl; for(int i=0; i<numberArray->size(); i++) delete numberArray->at(i); delete numberArray;
  • 24.
    vector methods sizeoperator[] push_back pop_back insert erase swap See: http://www.cplusplus.com/reference/stl/vector/
  • 25.
    C++: One toMany class Department { private: vector<Professor*>* members; public: Department(Professor* prof) { members = new Vector<Professor*>(); members->push_back(prof); } void addProfessor(Professor* prof) { members->push_back(prof); } ~Department() { delete members; } };
  • 26.
  • 27.
    Introduction to Polymorphism// This creates a pointer a, which has a memory address Dog* a; // This creates a new object to dynamic memory and returns memory address of the object, which is stored in a a = new Dog();
  • 28.
  • 29.
    Pointer Type differsfrom Object Type? // This creates a pointer a, which has a memory address Mammal* a; // This creates a new object to dynamic memory and returns memory address of the object, which is stored in a a = new Dog();
  • 30.
    Pointer type vs.Object type When declaring a new Pointer Mammal* pointer; This pointer can have reference to Mammal and all of it's derived classes! So this is acceptible: Mammal* pointer = new Mammal(); Mammal* pointer = new Dog(); Mammal* pointer = new Human(); Mammal* pointer = new Cat();
  • 31.
    C++ #include <iostream>using namespace std; class Mammal { }; class Human : public Mammal { }; class Dog : public Mammal { }; class Cat : public Mammal { }; int main() { Mammal* pointer1 = new Mammal(); Mammal* pointer2 = new Human(); Mammal* pointer3 = new Dog(); Mammal* pointer4 = new Cat(); // and remember to delete above: delete pointer1; delete ...
  • 32.
    Array class Mammal{ }; class Human : public Mammal { }; class Dog : public Mammal { }; class Cat : public Mammal { }; int main() { Mammal array[2]; Dog musti; Human pekka; array[0] = musti; array[1] = pekka; return 0; }
  • 33.
    vector class Mammal{ }; class Human : public Mammal { }; class Dog : public Mammal { }; class Cat : public Mammal { }; int main() { vector<Mammal> dynamicArray; Dog musti; Human pekka; dynamicArray.push_back(musti); dynamicArray.push_back(pekka); return 0; }
  • 34.
    vector: Everything intodynamic memory vector<Mammal*>* dynamicArray = new vector<Mammal*>(); dynamicArray->push_back( new Dog() ); dynamicArray->push_back( new Human() ); dynamicArray->push_back( new Mammal() ); dynamicArray->push_back( new Cat() ); for(int i=0; i < dynamicArray->size(); i++) delete dynamicArray->at(i); delete dynamicArray;
  • 35.
    Problem? void function(Mammal*m) { // m may hold Dog, Cat or // Human.. m->Bark(); }
  • 36.
    Casting void function(Mammal*m) { Dog* dog = dynamic_cast<Dog*>(m); dog->Bark(); }
  • 37.
    Type info #include<typeinfo> void function(Mammal* m) { Dog* temp = new Dog(); if(typeid(*temp) == typeid(*m)) { delete temp; Dog* dog= dynamic_cast<Dog*>(m); dog->Bark(); } }
  • 38.
  • 39.
    Zoo-example class Zoo{ private: vector<Animal*>* animals; public: Zoo() { animals = new Vector<Animal*>(); } void addAnimal(Animal* animal) { animals->push_back(animal); } ~Zoo() { delete animals; } };
  • 40.
    Inheritance Example (1/2)class Mammal { protected: string name_; public: void SetName(string name) { name_ = name; } }; class Human : public Mammal { }; class Dog : public Mammal { }; class Cat : public Mammal { };
  • 41.
    Inheritance Example (2/2)int main() { Human pekka; pekka.SetName(&quot;Pekka&quot;); Dog musti; musti.SetName(&quot;Musti&quot;); return 0; }
  • 42.
  • 43.
    C++ class Mammal{ protected: string name_; public: void SetName(string name) { name_ = name; } void PrintInformation() { cout << &quot;Hello, I'm mammal and my name is &quot; << name_ << endl; } }; class Human : public Mammal { public: void PrintInformation() { cout << &quot;Hello, I'm human and my name is &quot; << name_ << endl; } };
  • 44.
    C++ int main() { Human* pekka = new Human(); pekka->SetName(&quot;Pekka&quot;); // prints // Hello, I'm human and my name is Pekka pekka->PrintInformation(); delete pekka; return 0; }
  • 45.
    What about now?int main() { Mammal* pekka = new Human(); pekka->SetName(&quot;Pekka&quot;); // prints // Hello, I'm mammal and my name is Pekka pekka->PrintInformation(); delete pekka return 0; }
  • 46.
    Fix class Mammal{ protected: string name_; public: void SetName(string name) { name_ = name; } virtual void PrintInformation() { cout << &quot;Hello, I'm mammal and my name is &quot; << name_ << endl; } }; class Human : public Mammal { public: void PrintInformation() { cout << &quot;Hello, I'm human and my name is &quot; << name_ << endl; } };
  • 47.
    What about now?int main() { Mammal* pekka = new Human(); pekka->SetName(&quot;Pekka&quot;); // prints // Hello, I'm human and my name is Pekka pekka->PrintInformation(); delete pekka return 0; }
  • 48.
    Without Virtual A*p1 = new A(); p1->method(); B* p2 = new B(); p2->method(); A* p3 = new B(); p3->method();
  • 49.
    With Virtual A*p1 = new A(); p1->method(); B* p2 = new B(); p2->method(); A* p3 = new B(); p3->method();
  • 50.
    Virtual in Destructorsclass Mammal { public: Mammal() { cout << &quot;Mammal Constructor\n&quot;; } ~Mammal() { cout << &quot;Mammal Destructor\n&quot;; } }; class Human : public Mammal { public: Human() { cout << &quot;Human Constructor\n&quot;; } ~Human() { cout << &quot;Human Destructor\n&quot;; } }; Mammal* pekka = new Human(); delete pekka; Result: Mammal Constructor Human Constructor Mammal Destructor
  • 51.
    Virtual in Destructorsclass Mammal { public: Mammal() { cout << &quot;Mammal Constructor\n&quot;; } virtual ~Mammal() { cout << &quot;Mammal Destructor\n&quot;; } }; class Human : public Mammal { public: Human() { cout << &quot;Human Constructor\n&quot;; } ~Human() { cout << &quot;Human Destructor\n&quot;; } }; Mammal* pekka = new Human(); delete pekka; Result: Mammal Constructor Human Constructor Human Destructor Mammal Destructor
  • 52.
    Problem class Vehicle{ }; class Motor { }; class Car : public Vehicle { private: Motor* motor; public: Car() { motor = new Motor(); } ~Car() { delete motor; } }; int main() { Vehicle* datsun = new Car(); delete datsun; return 0; }
  • 53.
    Solution class Vehicle{ public: virtual ~Vehicle() { } }; class Motor { }; class Car : public Vehicle { private: Motor* motor; public: Car() { motor = new Motor(); } ~Car() { delete motor; } }; int main() { Vehicle* datsun = new Car(); delete datsun; return 0; }