c++多态公有继承

在实际开发中,可能会遇到这样的情况,即希望同一个方法在派生类和基类中的行为是不同的,换句话来说,方法的行为应取决于调用该方法的对象。这种较复杂的行为称为多态。即同一个方法的行为随上下文而异。有两种重要的机制可用于实现多态公有继承。

  • 在派生类中重新定义基类的方法。
  • 使用虚方法。

一,People类和Student类

  • people.h
#ifndef PEOPLE_H
#define PEOPLE_H

#include <iostream>
using namespace std;

class People
{
    
    
public:
    People();
    People(const string &name, const string &age);
	virtual ~People();
    
    void say();
    virtual void display();

protected:
    string m_name;
    string m_age;
};

class Student : public  People
{
    
    
public:
    Student(const string &name, const string &age, const string &score);
    Student(const string &score, const People *p);

    void study(const string &course);
    virtual void display();
private:
    string m_score;
};

#endif // PEOPLE_H

关于程序清单,有以下说明:

  1. Student类在People类的基础上添加了一个私有数据成员和一个公有成员函数
  2. Student类和People类都声明了display方法。但Student对象和People对象的这些方法的行为是不同的。
    两个display原型表明将有两个独立的方法定义.基类版本的限定名为People::display(), 派生类版本的限定名为Student::display()。程序将使用对象类型来确定使用哪个版本。
	People people("clc", "25");
    Student student("kalu", "24", "100");

    people.display();       //    clc  25   使用People::display()
    student.display();      //    kalu  24 100	使用Student::display()
  1. Student类在声明display是使用了关键字virtual, 该方法称为虚方法。
    该项要比前两点复杂,如果方法是用过引用或指针而不是对象调用的,它将确定使用哪一种方法。如果没有使用virtual关键字,程序将根据引用类型或指针类型选择方法;如果使用了virtual,程序将根据引用类型或指针指向的对象的类型来选择方法。
    如果display()不是虚的,则程序的行为如下:引用变量的类型为People,所以选择了People::display(),指针与此类似。
    People people("clc", "25");
    Student student("kalu", "24", "100");

    People &r_people = people;
    People &r_student = student;

    r_people.display();       //    clc  25		使用People::display()
    r_student.display();      //    kalu  24	使用People::display()

如果display()是虚的,则程序的行为如下:两个引用的类型都是People,但是r_student引用的是一个Student对象,所有使用的是Student::display()。指针与此类似。

	People people("clc", "25");
    Student student("kalu", "24", "100");

    People &r_people = people;
    People &r_student = student;

    r_people.display();       //    clc  25			使用People::display()
    r_student.display();      //    kalu  24 100	使用Student::display()

虚函数的这种行为非常方便,因此,经常在基类中将派生类会重新定义的方法声明为虚方法。方法在基类中被声明为虚的后,它在派生类将自动称为虚方法。
4. People类还声明了一个虚析构函数,这样做是为了确保释放对象时按正确的顺序调用析构函数。

  • 类实现 people.cpp
#include "people.h"

People::People()
{
    
    

}

People::People(const string &name, const string &age)
{
    
    
    m_name = name;
    m_age = age;
}

People::~People()
{
    
    

}

void People::say()
{
    
    
    cout << m_name << " is speak" << endl;
}

void People::display()
{
    
    
     cout << m_name << "  " << m_age << endl;
}

Student::Student(const string &name, const string &age, const string &score)
                : People (name, age)
{
    
    
    m_score = score;
}

void Student::study(const string &course)
{
    
    
    cout << m_name << " is study " << course << endl;
}

void Student::display()
{
    
    
    cout << m_name << "  " << m_age << " " << m_score << endl;
}
  • 派生类构造函数在初始化基类私有数据时,采用的是成员初始化列表,将基类信息传递给基类构造函数。
  • 非构造函数不能使用成员初始化列表。

二,使用People类和Student类

#include <iostream>
#include "people.h"

using namespace std;

int main()
{
    
    
    People people("clc", "25");
    Student student("kalu", "24", "100");

    people.say();
    student.say();					// 继承基类的方法

    people.display();
    student.display();				// 重写基类的虚方法

    student.study("English");		// 派生类新增方法
    return 0;
}

结果:

clc is speak
kalu is speak
clc  25
kalu  24 100
kalu is study English

三,演示虚方法的行为

假设要同时保存所有人的信息,如果能使用一个数组保存People和Student对象,将很有帮助,但这是不可能的,数组中所有元素的类型必须相同,而People和Student是不同的类型。然而,可以创建指向People的指针数组。这样,每个元素的类型都相同,但由于使用的是公有继承模型,因此People指针既可以指向People对象,又可以指向Student对象。因此,可以使用一个数组来表示多种类型的对象,这就是多态性。

#include <iostream>
#include "people.h"

using namespace std;

const int CLIENTS = 3;
int main()
{
    
    
    People people("clc", "25");
    Student student1("kalu", "24", "100");
    Student student2("alli", "25", "101");

    People * p_clients[CLIENTS];
    p_clients[0] = &people;
    p_clients[1] = &student1;
    p_clients[2] = &student2;

    for (int i = 0; i < CLIENTS; i++)
    {
    
    
        p_clients[i]->display();
    }
    return 0;
}
clc  25
kalu  24 100
alli  25 101

猜你喜欢

转载自blog.csdn.net/qq_43657810/article/details/127545336
今日推荐