WEBVTT

00:00.090 --> 00:00.600
Hello again!

00:00.870 --> 00:03.360
In this video, we are going to look at multiple inheritance.

00:04.530 --> 00:07.980
Multiple inheritance means that a derived class has more than one parent.

00:08.610 --> 00:10.620
It is rather a controversial subject!

00:11.190 --> 00:12.900
Many programmers and object-oriented

00:13.210 --> 00:19.050
designers have strong views about whether multiple inheritance is desirable, or even if it should be

00:19.050 --> 00:19.680
allowed at all!

00:20.340 --> 00:27.150
There are some languages which do not support inheritance. Java, for example. C++ does, which is

00:27.150 --> 00:28.650
why I am making this video.

00:30.240 --> 00:36.070
The main argument against multiple inheritance is that it adds complexity. It is even worse than

00:36.070 --> 00:40.830
single inheritance for creating very complicated hierarchies, full of duplicated code.

00:42.240 --> 00:45.360
However, if you use it intelligently, it can be a good thing.

00:45.990 --> 00:49.740
One situation where multiple inheritance is useful is for writing

00:49.740 --> 00:55.320
what are known as "mix-in" classes. If you have two classes which represent entirely separate concepts.

00:55.740 --> 01:00.990
For example, one class which interacts with files and another class which interacts with users.

01:01.590 --> 01:06.840
You could "mix" these into a single class which allows users to interact with files.

01:09.030 --> 01:13.770
As an example, we could have a TouchResponder class, which is part of the user interface.

01:14.040 --> 01:18.930
So this will it responds to mouse clicks, key presses, taps on a screen, and so on.

01:19.890 --> 01:25.230
Then we have a HardwareDevice class which communicates with the actual physical electronics, hardware.

01:25.980 --> 01:30.480
And then we have things like a mouse, a keyboard, a touch screen and so on, which combine both these

01:30.480 --> 01:31.020
properties.

01:31.710 --> 01:37.380
So we could write a Mouse class which inherits from the TouchResponder and also from the HardwareDevice.

01:37.980 --> 01:43.740
So this can respond to mouse button clicks, and also communicate with the physical mouse.

01:47.140 --> 01:52.600
To declare this Mouse class. It is similar to single inheritance, except we have more than one parent.

01:52.990 --> 01:54.910
So we put a comma between them.

01:55.690 --> 02:00.130
So the mouse class inherits from the HardwareDevice and the TouchResponder.

02:02.460 --> 02:05.340
Here is a very skeletal example.

02:05.350 --> 02:11.370
We have the HardwareDevice class, the TouchResponder class. And then we have the Mouse, Keyboard

02:11.370 --> 02:13.800
and TouchScreen which all inherit from these.

02:14.970 --> 02:16.830
And then we can create objects of that class.

02:17.280 --> 02:20.880
So that is allowed. In terms of memory layout,

02:20.880 --> 02:25.350
We have all the base classes at the start of the object, followed by the derived class.

02:27.450 --> 02:31.500
So for example, with the Mouse. We have the HardwareDevice at the start of memory, because that is

02:31.500 --> 02:37.890
declared first, then the TouchResponder, and then the actual derived object, the Mouse. The constructors

02:37.890 --> 02:39.030
will be called in the same order.

02:39.030 --> 02:45.480
So HardwareDevice constructor, then TouchResponder, then Mouse. For the destructors, that goes in the reverse

02:45.480 --> 02:45.800
order.

02:45.810 --> 02:48.640
So the Mouse destructor first, then TouchResponder,

02:49.040 --> 02:50.130
Then HardwareDevice.

02:53.570 --> 02:58.760
The derived class will inherit all the members of the parents, provided they were declared as public

02:58.760 --> 02:59.540
or protected.

03:00.320 --> 03:05.900
If we have the HardwareDevice with a get_data() member function, and the TouchResponder with

03:05.900 --> 03:07.160
a touch_down() function.

03:07.910 --> 03:12.440
Then we can write a member function for the Mouse class which will call the touch_down().

03:12.890 --> 03:18.890
So if the user clicks on a button. And then it can call the get_data() member function, to get the actual

03:18.980 --> 03:20.690
data from the physical device.

03:23.460 --> 03:26.100
So here is a rather more fleshed out skeleton.

03:26.910 --> 03:31.140
We have the HardwareDevice class, which has a constructor and destructor.

03:31.740 --> 03:36.960
It has the initialize() member function, which I will come back to in a minute. And then the get_data()

03:36.960 --> 03:37.350
member function.

03:39.670 --> 03:40.930
In the TouchResponder class.

03:40.930 --> 03:46.480
We have the initialize() function which has a different signature from the HardwareDevice one.

03:47.380 --> 03:48.940
Then we have the touch_down() function.

03:51.980 --> 03:56.090
And then in our Mouse class, we call the member functions it has inherited.

03:56.660 --> 04:01.940
So the mouse will inherit the get_data() and the initialize() from the HardwareDevice, and it will

04:01.940 --> 04:06.320
inherit touch_down() and initialize() from the Responder.

04:09.010 --> 04:13.330
And then, in the main() function, we can create a Mouse object, and call its process() member function.

04:15.850 --> 04:16.590
So there we are.

04:16.610 --> 04:19.180
The constructors are called in the order they were declared.

04:20.050 --> 04:25.330
Then we call the touch_down() and get_data() from the parent classes. And then the destructors are called, in

04:25.330 --> 04:26.110
reverse order.

04:29.580 --> 04:34.740
Now about this initialize() member function. What happens if we call this?

04:35.760 --> 04:38.110
You may think that this acts like an overload.

04:38.130 --> 04:42.220
We have one version which has a paramater reference

04:42.410 --> 04:44.280
argument and one version which has no argument.

04:44.940 --> 04:46.410
So the compiler should resolve this.

04:46.920 --> 04:50.280
But in fact, if we try to compile this, we get an error.

04:53.670 --> 04:55.380
"Ambiguous access of initialize".

04:55.710 --> 05:00.930
So even though the two functions have different signatures, the compiler cannot understand which one

05:00.930 --> 05:01.350
we want.

05:04.110 --> 05:06.420
So it is probably a bit hard to follow that in all the codes.

05:06.750 --> 05:07.650
Let's break it out.

05:08.010 --> 05:12.390
So we have the HardwareDevice initialize(), taking "params" by reference.

05:12.930 --> 05:15.420
We have the TouchResponder initialize(), with no arguments.

05:16.560 --> 05:19.890
And then we called initialize() for the mouse, with no arguments.

05:20.460 --> 05:24.990
The Mouse class will inherit both these member functions, so these are available to call.

05:25.560 --> 05:26.280
But if they -

05:26.760 --> 05:31.050
But if you have member functions which have the same name, they must only be defined in one parent.

05:31.560 --> 05:33.270
So that is why that did not compile.

05:35.750 --> 05:41.900
We can avoid this by writing the function initialize() for the Mouse class. And this can do whatever we

05:41.900 --> 05:42.740
need to do.

05:43.550 --> 05:48.320
If we are calling the parents, we need to give the class name, so the compiler will be clear which one we

05:48.320 --> 05:53.860
are calling. So we can call the initialize() memberfunction for the TouchResponder and then the HardwareDevice,

05:54.030 --> 05:54.530
member function.

05:57.140 --> 05:59.450
And then with the same code as before.

06:01.590 --> 06:08.370
But now we have the initialize() member function for the Mouse. And then we can call this from the main() function.

06:09.360 --> 06:11.400
Okay, so that is it for this video.

06:11.550 --> 06:12.420
I will see you next time.

06:12.420 --> 06:14.580
But until then, keep coding!
