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

  • Expert C++
  • Vardan Grigoryan Shunguang Wu
  • 419字
  • 2021-06-24 16:34:04

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.

主站蜘蛛池模板: 林周县| 交城县| 天峨县| 台南市| 湘潭县| 巫山县| 洛隆县| 东乌| 茌平县| 安顺市| 奉化市| 宣城市| 临澧县| 吉隆县| 太白县| 武义县| 高邮市| 连平县| 九龙坡区| 红桥区| 喀喇| 兴隆县| 淮安市| 绥宁县| 额尔古纳市| 托克托县| 禄丰县| 祁连县| 永平县| 淮安市| 商丘市| 凤冈县| 惠东县| 泸州市| 疏勒县| 密云县| 曲阳县| 黑山县| 瓦房店市| 赤城县| 昌平区|