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 a” relationship
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.
Related Topics
Privacy Policy, Terms and Conditions, DMCA Policy and Compliant
Copyright © 2018-2023 BrainKart.com; All Rights Reserved. Developed by Therithal info, Chennai.