官术网_书友最值得收藏!

Polymorphism

Polymorphism is another key concept in object-oriented programming. It allows subclasses to have their own implementation for the functions that are derived from the base class. Let's suppose we have the Musician class, which has the play() member function:

class Musician {
public:
void play() { std::cout << "Play an instrument"; }
};

Now, let's declare the Guitarist class, which has the play_guitar() function:

class Guitarist {
public:
void play_guitar() { std::cout << "Play a guitar"; }
};

This is the obvious case of using inheritance because the Guitarist just screams that it is-a Musician. It would be natural for the Guitarist to not extend the Musician by adding a new function (such as play_guitar()); instead, it should provide its own implementation of the play() function derived from the Musician. To accomplish this, we use virtual functions:

class Musician {
public:
virtual void play() { std::cout << "Play an instrument"; }
};

class Guitarist : public Musician {
public:
void play() override { std::cout << "Play a guitar"; }
};

Now, it's obviously simple that the Guitarist class provides its own implementation to the play() function and that the client code can access it by just using the pointer to the base class:

Musician armstrong;
Guitarist steve;
Musician* m = &armstrong;
m->play();
m = &steve;
m->play();

The preceding example shows polymorphism in action. While the use of virtual functions comes naturally, it actually doesn't make much sense unless we use it properly. First of all, the play() function of the Musician should not have any implementation at all. The reason for this is simple: a musician should be able to play on a concrete instrument as they cannot play on more than one instrument simultaneously. To get rid of the implementation, we set the function as a pure virtual function by assigning 0 to it:

class Musician {
public:
virtual void play() = 0;
};

This leads to a compile error when the client code tries to declare an instance of the Musician. And, of course, it must lead to a compile error, because you shouldn't be able to create an object that has an undefined function. The Musician serves a single purpose: it must only be inherited by other classes. The class that exists to be inherited is called an abstract class. Actually, the Musician is called an interface rather than an abstract class. An abstract class is a semi-interface semi-class that can have both types of functions: with and without implementation. 

Getting back to our example, let's add the Pianist class, which also implements the Musician interface:

class Pianist : public Musician {
public:
void play() override { std::cout << "Play a piano"; }
};

To express the full power of polymorphism, let's suppose that we have a function declared somewhere that returns a collection of musicians, either guitarist or pianists:

std::vector<Musician*> get_musicians();

From the perspective of the client code, it will be hard to dissect the return value of the get_musicians() function and find out what the actual subtype of the object is. It could be either Guitarist or Pianist, or even a pure Musician. The point is that the client shouldn't really care about the actual type of objects as it knows that the collection contains Musicians and a Musician object has the play() function. So, to get them in action, the client can just iterate through the collection and make each musician play its instrument (each object calls its implementation):

auto all_musicians = get_musicians();
for (const auto& m: all_musicians) {
m->play();
}

The preceding code expresses the full power of polymorphism. Now, let's understand how the language supports polymorphism at a low level.

主站蜘蛛池模板: 饶河县| 论坛| 武隆县| 雷山县| 苍南县| 昭通市| 苏尼特右旗| 新民市| 县级市| 济宁市| 威信县| 特克斯县| 重庆市| 武山县| 大石桥市| 丽水市| 缙云县| 泗水县| 修水县| 南丹县| 崇信县| 甘泉县| 纳雍县| 永宁县| 屏边| 安平县| 仙居县| 乌拉特后旗| 襄汾县| 汽车| 民乐县| 新余市| 曲周县| 来宾市| 长乐市| 德清县| 临夏县| 大竹县| 商丘市| 金寨县| 朝阳区|