CPP Aggregation and Delegation

What is Aggregation and Delegation in C++?

  • You can look at Aggregation as an alternative inheritance type not as a "is-a" relationship, but a "has-a" relationship to objects in a class.
  • This is to declare objects as a members of another class, which can says to be the containing class of those members.
    class Name {
       // Declaration and Implementation for Name Class
    };
    class Address {
       // Declaration and Implementation for Address Class 
    };
    . . . .
    class Employee {
    // Aggregated objects in form of a "has-a" relationship 
       Name    EmpName;
       Address EmpAddress;
       // Any other Employee Class stuff...
    }
  • A containing class that aggregates other objects does not have special access to those object's member data and methods, as the existing possibility for "is-a" relationship.
  • Delegation is to use the members of an aggregated class to perform functions for the containing class.
    Aggregate Inheritance and Delegation using a Linked List example:
    #include <string>
    #include <iostream>
    using namespace std;
    
    // BaseObject class must be a base class
    // for all objects handle by the linked list
    class BaseObject {
    protected:
    // The name is protected and can then be changed
    // by a drived class
      string name;
    public:
      // Make destructor virtual for all derived Classes
      // so cleanup can be done in those derived Classes
      virtual ~BaseObject() {}
      // Make a pure virtual method that must be implemented
      // by a driven class and makes this class abstract  
      virtual string getName() const =0;
    };
    
    // This is the class we want the linked List should handle
    class Person : public BaseObject {
    public:
      Person (string name, int age, int weight){
        this->name=name;
        this->age = age;
        this->weight = weight;
        cout << name << " Constructor ...\n";
      }
      ~Person() {cout << name << " Destructor ...\n";}
      string getName() const { return name; }
      int getAge() { return age; }
      int getWeight() { return weight; }
    private:
      int age;
      int weight;
    };
    
    // In a Linked list we use objects of the Node class
    // Each Node object contain pointer to an object
    // driven by the BaseObject class and a pointer to next
    // Node in the list
    class Node {
    private:
      Node * pNext;
      BaseObject * baseObject;
    public:
      Node( BaseObject * baseObject):pNext(0) {
        cout << baseObject->getName() << " Node Constructor ...\n";
        this->baseObject=baseObject;
      }
      ~Node(){
        if (pNext!=0) {
          delete pNext;
          pNext=0;
        }
        cout << baseObject->getName() << " Node Destructor ...\n";
        delete baseObject;
      }
      BaseObject * getBaseObject() {
        return baseObject;
      }
      Node * getNext() {
        return pNext;
      }
      void setNext(Node * pNext) {
        this->pNext=pNext;
      }
    };
    
    // The NodeManager class is a "worker class" 
    // and is been delegated by the LinkedList class
    // to manage the linked list
    class NodeManager {
      Node * pHead;  // pointer to first node in the linked list
      Node * pLast;  // pointer to last node in the linked list
      int size;      // nodes in the list
    public:
      NodeManager():pHead(0),pLast(0), size(0) {}
      ~NodeManager(){
        if (pHead!=0) {
          delete pHead;
          pHead=0;
        }
      }
      /*
      Add an Node with an BaseObject pointer to the linked list
      */
      void addNode(BaseObject * baseObject) {
        Node * p = new Node(baseObject);
        Node * pTemp=pLast;
        if (pLast==0)  {
          pHead=p;
          pLast=p;
        }else  {
          pLast->setNext(p);
          pLast=p;
        }
        size++;
      }
      /*
      We like to
      return an array of BaseObject pointer reference
      that exist in the Linked List instead of the Linked List
      For this we must return a pointer to pointer to an object
      driven by the BasObject Class
      */
      BaseObject * * getObjectArray() {
        BaseObject * * pBaseObject = new BaseObject*[size];
        int i=0;
        Node * pNode=pHead;
        while ( i < size) {
    //  *(pBaseObject+i)=pNode->getBaseObject(); // this is an alternative coding
          pBaseObject[i]=pNode->getBaseObject();
          i=i+1;
          pNode = pNode->getNext();
        }
        return pBaseObject;
      }
      // return the array size
      int getSize() {return size;}
    };
    
    class NodeList {
    private:
      // This is a has-a relationship to the NodeManager
      // that take care of the linked list
      // It is private and cannot be accessed 
      // without a NodeList object
      NodeManager nodeManager;
    public:
      void addObject(BaseObject * baseObject) {
        nodeManager.addNode(baseObject);
      }
      BaseObject * * getObjectArray() {
        return nodeManager.getObjectArray();
      }
      // return the array size
      int getSize() {return nodeManager.getSize();}
    };
    
    int main () {
      NodeList nodeList;
      nodeList.addObject(new Person("Ricard",20,60));
      nodeList.addObject(new Person("Frank",22,62));
      nodeList.addObject(new Person("Obama",26,76));
      Person * * persons = (Person* *)nodeList.getObjectArray();
      cout << "\n";
      for (int i=0 ; i < nodeList.getSize() ; i++)  {
        // (*(persons+i))->getName();  is the same as  persons[i]->getName();
        string name=persons[i]->getName();
        cout << name << " is " << persons[i]->getAge() << " old ";
        cout << "and has a weight of " << persons[i]->getWeight() << "\n";
      }
      cout << "\n";
      return 0;
    }
    When we run this application, the result will be:
    Ricard Constructor ...
    Ricard Node Constructor ...
    Frank Constructor ...
    Frank Node Constructor ...
    Obama Constructor ...
    Obama Node Constructor ...
    
    Ricard is 20 old and has a weight of 60
    Frank is 22 old and has a weight of 62
    Obama is 26 old and has a weight of 76
    
    Obama Node Destructor ...
    Obama Destructor ...
    Frank Node Destructor ...
    Frank Destructor ...
    Ricard Node Destructor ...
    Ricard Destructor ...
    You can download this example here (needed tools can be found in the right menu on this page).
© 2010 by Finnesand Data. All rights reserved.
This site aims to provide FREE programming training and technics.
Finnesand Data as site owner gives no warranty for the correctness in the pages or source codes.
The risk of using this web-site pages or any program codes from this website is entirely at the individual user.