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

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.

主站蜘蛛池模板: 遂平县| 白城市| 公主岭市| 福贡县| 长顺县| 芒康县| 内江市| 滦平县| 宜兰县| 黄骅市| 堆龙德庆县| 朔州市| 云林县| 岳西县| 金秀| 巴南区| 桐庐县| 体育| 汕头市| 富阳市| 上思县| 泗阳县| 阿瓦提县| 武隆县| 张家口市| 菏泽市| 措勤县| 三明市| 伊金霍洛旗| 年辖:市辖区| 徐汇区| 南澳县| 汉阴县| 凌海市| 峨眉山市| 西城区| 藁城市| 福泉市| 河北省| 清镇市| 兴文县|