Home | | Object Oriented Programming and Data Structures | Composition vs. Inheritance

Chapter: Object Oriented Programming and Data Structure : Inheritance and Polymorphism

Composition vs. Inheritance

Pointers to Member Functions and Pointers to Data Members , Declaring Pointers to Data Members

Composition vs. Inheritance

 

"is a" relationship Inheritance

"has a" relationship

Composition - class has an object from another class as adata member

 

Employee “is a” BirthDate; //Wrong!

 

Employee “has a” Birthdate;//Composition

“Uses A” And “Knows A” Relationships “uses a” relationship

 

One object issues a function call to a member function of another object

knows arelationship

One object is aware of another

– Contains a pointer or handle to another object Also called an association

 

Pointers to Member Functions and Pointers to Data Members

 

A class can have two general categories of members: functions and data members. Similarly, there are two categories of pointers to members: pointers to member functions, and pointers to data members. The latter are less common because you rarely have direct access to data members. However, when using legacy C code with structs or classes have public data members, pointers to data members might be useful.

 

Declaring Pointers to Data Members

 

The syntax of pointers to members might look confusing at first, but it's consistent. The syntax resembles the form of ordinary pointers to functions, with the addition of the class name followed by the operator ::. For example, if an ordinary pointer to int looks like this:

 

int * pi;

 

you define a pointer to an int member of class A like this:

class A{/**/};

 

int A::*pmi; // pmi is a pointer to an int member of A

You can initialize pmi like this:

class A

{

public:

intnum;

int x;

};

 

int A::*pmi = &A::num; // 1

 

Manipulating a data member through an object

 

The statement numbered 1 defines a pointer to an int member of class A and initializes it with the address of num. Now you can use the pointer pmi to examine and modify num's value in any object of class A:

 

A a1; A a2;

 

int n = a1.*pmi; // copy the value of a1.num to n

a1.*pmi = 5; // assign the value to a1.num

a2.*pmi = 6; // assign the value 6 to a2.num

 

Manipulating a data member through an object's pointer

 

Similarly, you can access a data member through a pointer to A like this:

A * pa = new A;

 

int n = pa->*pmi; // assign to n the value of pa->num

pa->*pmi = 5; // assign the value 5 to pa->num

 

Or using a pointer to an object derived from A:

class D : public A {};

A* pd = new D;

pd->*pmi = 5; // assign the value 5 to pd->num

 

Declaring Pointers to Member Functions

 

Thus far, I've focused on pointers to data members, which are used less often than pointers to member functions. A pointer to a member function consists of the member function's return type, the class name followed by ::, the pointer's name, and the function's parameter list. For example, a pointer to a member function of class A that returns int and takes no arguments looks like this (note that both pairs of parentheses are mandatory):

 

class A

{

 

public: intfunc ();

};

 

int (A::*pmf) ();

/* pmf is a pointer to some member function of class A that returns int and takes no arguments*/

 

In fact, a pointer to a member function looks just like an ordinary pointer to function, except that it also contains the class's name immediately followed by the :: operator. You can invoke the member function to which pmf points like this:

pmf = &A::func; //assign pmf

A a;

A *pa = &a;

(a.*pmf)(); // invoke a.func()

 

// call through a pointer to an object (pa->*pmf)(); //

calls pa->func()

 

Pointers to member functions respect polymorphism; if you call a virtual member function through a pointer to member, the call will be resolved dynamically as the following code shows:

 

class Base

{

public:

 

virtualint f (int n);

};

 

class Derived : public Base {

public:

 

int f (int h); //override

};

Base *pb = new Derived;

 

int (Base::*pmf)(int) = &Base::f;

(pb->*pmf)(5); // call resolved as D::f(5);

Note that you cannot take the address of constructors and destructors.

 

The Underlying Representation of Pointers to Members

 

Although pointers to members behave like ordinary pointers, behind the scenes their representation is quite different. In fact, a pointer to member usually consists of a structure containing up to four fields in certain cases. This is because pointers to members have to support not only ordinary member functions, but also virtual member functions, member functions of objects that have multiple base classes, and member functions of virtual base classes. Thus, the simplest member function can be represented as a set of two pointers: one holding the physical memory address of the member function, and a second pointer that holds the this pointer. However, in cases like a virtual member function, multiple inheritance and virtual inheritance, the pointer to member must store additional information. Therefore, you can't cast pointers to members to ordinary pointers nor can you safely cast between pointers to members of different types.

 

To get a notion of how your compiler represents pointers to members, use the size of operator. In the following example, the sizes of a pointer to data member and a pointer to a member function are taken. As you can see, they have different sizes, hence, different representations:

 

struct A

{

 

int x;

void f();

};

 

int A::*pmi = &A::x;

 void (A::*pmf)() = &A::f;

 

int n = sizeof (pmi); // 8 byte with my compiler

int m = sizeof (pmf); // 12 bytes with my compiler

Note that each of these pointers may have a different representation, depending on the class in question and whether the member function is virtual.

 

Function Overriding

 

If base class and derived class have member functions with same name and arguments. If you create an object of derived class and write code to access that member function then, the member function in derived class is only invoked, i.e., the member function of derived class overrides the member function of base class. This feature in C++ programming is known as function overriding.

 

Accessing


 

Accessing the Overridden Function in Base Class From Derived Class

To access the overridden function of base class from derived class, scope resolution operator

::. For example: If you want to access get_data() function of base class from derived class in above example then, the following statement is used in derived class.

A::get_data; // Calling get_data() of class A.

It is because, if the name of class is not specified, the compiler thinks get_data() function is

calling itself.



Study Material, Lecturing Notes, Assignment, Reference, Wiki description explanation, brief detail
Object Oriented Programming and Data Structure : Inheritance and Polymorphism : Composition vs. Inheritance |


Privacy Policy, Terms and Conditions, DMCA Policy and Compliant

Copyright © 2018-2023 BrainKart.com; All Rights Reserved. Developed by Therithal info, Chennai.