Topics Covered:
C++ distinguishes between 3 kinds of derivations: public,
private, and protected The differences between them are summarizd
in this table:(courtesy Richard Chang)
In the base class, the inherited member is a: | |||
---|---|---|---|
Access From | Public Member | Protected Member | Private Member |
Members & friends of a derived class | Yes | Yes | No |
Members & friends of a subsequently derived class | if previous
derivations are public or protected | if previous derivations are public or protected | No |
Other functions, using a derived object | if derivation is public | No | No |
Friend functions of a base class are not friends of the derived class
Consider the package class, package.h (links to all files are given above). It is a private derivation from box, which means that the function grow, which was public in box, cannot be used by nonmember functions accessing packages. This prevents us from having a box that is inside another one change its dimensions, and violating the idea that a package can hold only other packages which are smaller than it.
The first program main1.C has a function foo which takes a person& as an argument and a function bar, taking a Person*. (since student and faculty are both also of type person, we can pass them to foo and to bar with no typecasts - this is another way of saying that a derived class is compatible with the base class) . (a href="lec19/derive2/main1.txt"> output
the second program shows that pointer assignment also works in that we can cause a pointer to a base class to point to an object of the derived class; but the call ptr->id() gets the base class's id always, because the pointer dereferences as a person typeoutput
We can show that a pointer to a pointer to a person is not assignment
compatible with a pointer to pointer to student - because if it were,
I could do some weird stuff:
Person **p1, **p2; Student S1("Joe", 19, 2, 3.79); Faculty F1("Dr. Who", 49, 15); Student * sp1 = &S1; //points to student Faculty * fp1 = &F1; // points to faculty; p1 = &sp1; //p1 points to student pointer p2 = &fp1; //p2 points to faculty pointer *p1 = *p2; //replace what p1 points to by what p2 points tonow, sp1 points to a faculty object, but this is not good. student and faculty objects occupy differnet amounts of storage, and this assignment can get us into some serious trouble.
Program 4 has a function SortByAge,
which uses selection sort to sort an array of persons.
output
Suppose we use SortByAge to sort an array of students, The programand its output show the effect of trying to use SortbyAge to sort an array of students. Even though student pointers are assignment compatible with person pointers, the size of the objects being pointed to are different, and when we try to move these objects about in memory, we get into trouble. The address of the second object in an array of persons is A+sizeof(Person), which is not equal to A+sizeof(student). If we make SortbyAge sort an array of person pointers, as in program 6, and then typecast an array of pointer to students as person pointers. Even though the output shows that we can do it, it is considered bad programming practice ot do this kind of finagling.
If we try a slightly different apporach, making an array of person pointers point to students (as in thsi example, we can sort the array of students, but not id them as students. (a href="lec19/derive2/main7.txt">Output
The way around all these difficulties is in creating a virtual base clss. person2.h shows how this is done. Notice that the id function is declared as virtual in the base class, and when the compiler dereferences a pointer to a person, it figures out what kind of person it is pointing to - person, student, faculty, and then invokes the id function appropriate to that type. code and Output