C++对象向上转型

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_25203255/article/details/78827628

1. 什么是对象向上转型

将派生类对象赋值给基类对象、将派生类指针赋值给基类指针、将派生类引用赋值给基类引用,这在 C++ 中称为向上转型(Upcasting)。
理解基类和派生类之间的类型转换是理解C++语言面向对象编程的关键所在。(出自《c++ primer》)

2. 对象向上转型

对象之间不存在对象转型,转换过程中会忽略派生类的部分。因此,在这种转换的实际发生过程往往与我们期待的有所差别。
在对象指针或引用转换过程中,存在静态绑定和动态绑定,转换时非虚函数通常都是以静态绑定进行的,而虚函数是以动态绑定进行的。如下图:
这里写图片描述
因为,虚函数是以动态绑定的,因此,在向上转型后也是匹配的派生类的版本。而派生类的其他方法和属性都被隐藏了,可以通过专门的虚函数来间接访问或者调用。

3. 实例

#include <iostream>

using namespace std;

class A {

public:
    A() : m(20) {}
    void show() { cout << "A show: " << m << endl; }
    virtual void display() { cout << "A display: " << m << endl; }

private:
    int m;

};

class B : public A
{

public:
    B() : m(40) {}
    void show() { cout << "B show: " << m << endl; }
    virtual void display() { cout << "B display: " << m << endl; }

private:
    int m;

};

int main()
{
    // 定义上执行对象
    A* a = new B;
    // 调用静态绑定的方法show
    a->show();
    // 调用动态绑定的方法display
    a->display();
    return 0;
}

虽然show方法基类和派生类都定义了,但因为是静态绑定,因此调用的是class A的show方法; 而display方法是动态绑定,因此在转型过程中绑定的是派生类的方法。运行结果如下:

A show: 20
B display: 40

4. 运用

学生管理系统中,我们拥有3个用户:管理员、教师和学生。他们都拥有一个用户id和其他一些共有的属性特性外,学生还拥有学号、班级等信息属性;教师拥有职工号和工资等信息属性;管理员也拥有一些特有属性。
通过问题分析得到一个大致设计思路,我们可以通过定义一个User类来管理3种类型用户的共有属性和方法,在通过继承User类进一步实现管理学生的Student类,管理教师信息的Teacher类, 管理管理员信息的Admin类。如果Student类、Teacher类和Admin类都具有一个方法show(),用以实现显示不同类型用户的信息,那么当不同类型用户登陆后如何显示显示其登陆用户的信息?

这问题有很多解决方法,比如下面这代码就是一种方法:

#include <iostream>

using namespace std;

class User {

public:
    User() {}

    /** 省略部分 **/

private:
    /** 省略部分 **/

};

class Student : public User
{

public:
    Student()  {}
    void show() { cout << "登陆用户是学生" << endl; }

    /** 省略部分 **/

private:
    /** 省略部分 **/

};

class Teacher : public User
{

public:
    Teacher()  {}
    void show() { cout << "登陆用户是教师" << endl; }

    /** 省略部分 **/

private:
    /** 省略部分 **/

};

class Admin : public User
{

public:
    Admin()  {}
    void show() { cout << "登陆用户是管理员"  << endl; }

    /** 省略部分 **/

private:
    /** 省略部分 **/

};

int main()
{
    // 定义3中类型用户
    Student* student = nullptr;
    Teacher* teacher = nullptr;
    Admin* admin = nullptr;
    int userType; // 用户类型
    cout << "选择用户类型(1. 管理员  2. 教师  3. 学生),清选择: ";
    cin >> userType;
    /** 省略部分登陆操作  **/
    if(userType == 1)
        admin = new Admin;
    else if(userType == 2)
        teacher = new Teacher;
    else if(userType == 3)
        student = new Student;

    /** 显示信息  **/
    if(userType == 1)
        admin->show();
    else if(userType == 2)
        teacher->show();
    else if(userType == 3)
        student->show();

    /**  省略部分注销操作  **/
    if(userType == 1)
        delete admin;
    else if(userType == 2)
        delete teacher;
    else if(userType == 3)
        delete student;
    return 0;
}

可以看出非常的累赘,对象向上转型就可以用来简化代码了,如下代码:

#include <iostream>

using namespace std;

class User {

public:
    User() {}
    virtual void show() = 0;

    /** 省略部分 **/

private:
    /** 省略部分 **/

};

class Student : public User
{

public:
    Student()  {}
    void show() { cout << "登陆用户是学生" << endl; }

    /** 省略部分 **/

private:
    /** 省略部分 **/

};

class Teacher : public User
{

public:
    Teacher()  {}
    void show() { cout << "登陆用户是教师" << endl; }

    /** 省略部分 **/

private:
    /** 省略部分 **/

};

class Admin : public User
{

public:
    Admin()  {}
    void show() { cout << "登陆用户是管理员"  << endl; }

    /** 省略部分 **/

private:
    /** 省略部分 **/

};

int main()
{
    User* user = nullptr;
    int userType; // 用户类型
    cout << "选择用户类型(1. 管理员  2. 教师  3. 学生),清选择: ";
    cin >> userType;
    /** 省略部分登陆操作  **/
    if(userType == 1)
        user = new Admin;
    else if(userType == 2)
        user = new Teacher;
    else if(userType == 3)
        user = new Student;

    user->show();
    delete user;

    return 0;
}

可以看出对象向上转型可以在某些环境中是非常好用的特性。

猜你喜欢

转载自blog.csdn.net/qq_25203255/article/details/78827628