c++多态

多态概念引入

多态字面意思就是多种形态。
我们先来想一想在日常生活中的多态例子:买票时,成人买票全价,如果是学生那么半价,如果是军人,就可以优先买票。不同的人买票会有不同的实现方法,这就是多态。

C++多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不同的函数; 形成多态必须具备三个条件:

  • 1. 必须存在继承关系;
  • 2. 继承关系必须有同名虚函数(其中虚函数是在基类中使用关键字 virtual 声明的函数,在派 生类中重新定义基类中定义的虚函数时,会告诉编译器不要静态链接到该函数);
  • 3. 存在基类类型的指针或者引用,通过该指针或引用调用虚函数。 这里我们还需要理解两个概念:

虚函数:

是在基类中使用关键字 virtual 声明的函数。在派生类中重新定义基类中定义的虚函数时, 会告诉编译器不要静态链接到该函数。我们想要的是在程序中任意点可以根据所调用的对象类 型来选择调用的函数,这种操作被称为动态链接,或后期绑定。虚函数声明如下:virtual ReturnType FunctionName(Parameter) 虚函数必须实现,如果不实现,编译器将报错

纯虚函数: 

若在基类中定义虚函数,以便在派生类中重新定义该函数更好地适用于对象,但是您在基 类中又不能对虚函数给出有意义的实现,这个时候就会用到纯虚函数。纯虚函数声明如下: virtual void funtion1()=0; 纯虚函数一定没有定义,纯虚函数用来规范派生类的行为,即接口。 包含纯虚函数的类是抽象类,抽象类不能定义实例,但可以声明指向实现该抽象类的具体类的 指针或引用。

#include 
#include 

using namespace std;

/* 定义一个动物类 */
class Animal
{
public:
    virtual void run()
    {
        cout <<"Animal的run()方法"<run();

     /* 存储 cat 对象的地址 */
    animal = &cat;
    /* 调用 run()方法 */
    animal->run();

    return 0;
}

其中我们可以看到基类 Animal 类的 run() 方法前面加了关键字 virtual。这样让基类 Animal 类的 run()方法变成了虚函数。在这个例子里 我们可以知道虚函数是 C++中用于实现多态(polymorphism)的机制。核心理念就是通过基类访 问派生类定义的函数。简单的来说,上面的实例是基类 Animal 声明了一个指针 animal。然后通 过基类的指针来访问 Dog 类对象与 Cat 类的对象的 run()方法,前提是基类的 run()方法必须声 明为虚函数,如果不声明为虚函数,基类的指针将访问到基类自己的 run()方法。

编译完成执行的结果如下。

c++多态_第1张图片

 

数据封装

封装是面向对象编程中的把数据和操作数据的函数绑定在一起的一个概念,这样能避免受 到外界的干扰和误用,从而确保了安全。数据封装引申出了另一个重要的 OOP 概念,即数据 隐藏。

数据封装是一种把数据和操作数据的函数捆绑在一起的机制,数据抽象是一种仅向用户暴 露接口而把具体的实现细节隐藏起来的机制,C++ 通过创建类来支持封装和数据隐藏(public、 protected、private)。 

任何带有公有和私有 成员的类都可以作为数据封装和数据抽象的实例。通常情况下,我们都会设置类成员状态为私 有(private),除非我们真的需要将其暴露,这样才能保证良好的封装性。这通常应用于数据成 员,但它同样适用于所有成员,包括虚函数。

 

#include 
#include 

using namespace std;
class Dog
{
public:
    string name;
    Dog(int i = 0) 
    {
        total = i;
    }
    void addFood(int number)
    {
        total = total + number;
    }
    int getFood()
    {
        return total;
    }

private:
    int total;
};

int main()
{
    Dog dog;
    dog.name = "旺财";
    dog.addFood(3);
    dog.addFood(2);
    cout<

编译完成执行的结果如下。

c++多态_第2张图片

 

数据抽象

数据抽象是指,只向外界提供关键信息,并隐藏其后台的实现细节,即只表现必要的信息 而不呈现细节。数据抽象是一种依赖于接口和实现分离的编程(设计)技术。

数据抽象的好处: 

  • 1. 类的内部受到保护,不会因无意的用户级错误导致对象状态受损。
  • 2. 类实现可能随着时间的推移而发生变化,以便应对不断变化的需求,或者应对那些要 求不改变用户级代码的错误报告。

举个简单的例子,比如我们生活中的手机。手机可以拍照、听音乐、收音等等。这些都是 手机上的功能,用户可以直接使用。但是拍照的功能是如何实现的,是怎么通过摄像头取像然 后怎么在屏幕上显示的过程,作为用户是不需要知道的。也就是暴露的不用太彻底,用户也不 必须知道这种功能是如何实现的,只需要知道如何拍照即可。

就 C++ 编程而言,C++ 类为数据抽象提供了可能。它们向外界提供了大量用于操作对象 数据的公共方法,也就是说,外界实际上并不清楚类的内部实现。

其实像 cout 这个对象就是一个公共的接口,我们不必要知道 cout 是如何在屏幕上显示内容 的。cout 已经在底层实现好了。

数据封装是一种把数据和操作数据的函数捆绑在一起 的机制,而数据抽象是一种仅向用户暴露接口而把具体的实现细节隐藏起来的机制。

接口(抽象类)

接口描述了类的行为和功能,而不需要完成类的特定实现。C++ 接口是使用抽象类来实现 的,抽象类与数据抽象互不混淆,数据抽象是一个把实现细节与相关的数据分离开的概念。如 果类中至少有一个函数被声明为纯虚函数,则这个类就是抽象类纯虚函数是通过在声明中使 用 "= 0" 来指定的。

设计抽象类(通常称为 ABC)的目的,是为了给其他类提供一个可以继承的适当的基类。 抽象类不能被用于实例化对象,它只能作为接口使用。如果试图实例化一个抽象类的对象,会 导致编译错误。

因此,如果一个 ABC 的子类需要被实例化,则必须实现每个虚函数,这也意味着 C++ 支 持使用 ABC 声明接口。如果没有在派生类中重写纯虚函数,就尝试实例化该类的对象,会导 致编译错误。可用于实例化对象的类被称为具体类。

#include 

using namespace std;

 /* 定义一个动物类 */
class Animal
{
public:
    virtual void run() = 0;
};

 /* 定义一个狗类,并继承动物类 */
 class Dog : public Animal
 {
public:
    void run() {
        cout<<"Dog 的 run()方法"<

程序运行的结果如下。

c++多态_第3张图片

你可能感兴趣的:(c++,开发语言)