C++多态学习之向下强制类型转换

Wesley13
• 阅读 1167

向下强制类型转换

在C++中,基类(父类)指针可以指向派生类(子类)对象,因为派生类对象也是一个基类对象(但反过来不一样,基类对象不是一个派生类对象)。然而基类指针只能调用基类的成员函数,如果试图使用该指针调用仅在派生类中含有的成员函数(子类特有的,不是继承和重写父类的函数),将会产生编译错误。为了避免这一错误,就必须将基类指针转换成为派生类指针。《C++大学教程第13章,面向对象编程:多态性》

如何进行向下强制类型转换

在C++使用 dynamic_cast 关键字进行向下强制类型转换,代码如下所示:

class Base{//基类
public:
    Base(){}//构造函数
    virtual void print()const{//虚函数print
        cout << "父类的print函数"<< endl;
    }

};

class A:public Base{//子类A
public:
    A(){}//构造函数
    virtual void print()const{//
        cout << "子类A的print函数" << endl;
    }
};

class B:public Base{//子类B
public:
    B(){}//构造函数
    virtual void print()const{//
        cout << "子类B的print函数" << endl;
    }
};

int main(){
    Base *pbase = nullptr;
    A a, *pa = nullptr;
    B b, *pb = nullptr;

    pbase = &a;//基类指针指向子类A对象
    cout << "pbase是基类指针,但是指向的是子类A的对象" << endl;
    pbase->print();//基类指针调用虚函数print,多态,将调用子类A的print

    cout << endl <<"pbase是基类Base类型的指针\n" << "我们将其转换为子类A的指针:" ;
    pa = dynamic_cast< A* >(pbase);
    //向下强制类型转换,本来pbase指向的是子类A的对象,因此,该转换是成功的
    if(nullptr != pa){
        cout << "向下强制转换成功" << endl;
    }else{
        cout << "向下强制转换失败" << endl;
    }

    cout << "\n现在我们将其转换为子类B的指针:";
    pb = dynamic_cast< B* >(pbase);
    //此时pbase还是指向子类A的对象,我们让pbase强制转换成子类B的对象,转失败
    if(nullptr != pb){
        cout << "向下强制转换成功" << endl;
    }else{
        cout << "向下强制转换失败" << endl;
    }

    //pbase = &b;
   // pbase->print();//调用子类B的print函数

    return 0;
}

运行结果如下:

C++多态学习之向下强制类型转换

在进行强制类型转换后一般需要判断强制转换是否成功,然后在接着执行进一步操作。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Wesley13 Wesley13
3年前
java8新特性
Stream将List转换为Map,使用Collectors.toMap方法进行转换背景:User类,类中分别有id,name,age三个属性。List集合,userList,存储User对象1、指定keyvalue,value是对象中的某个属性值。 Map<Integer,StringuserMap1userList.str
Wesley13 Wesley13
3年前
java中经常问到的面试题
1、面向对象编程的三大特性是什么?(1).继承:继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法。对象的一个新类可以从现有的类中派生,这个过程称为类继承。新类继承了原始类的特性,新类称为原始类的派生类(子类),而原始类称为新类的基类(父类)。派生类可以从它的基类那里继承方法和实例
待兔 待兔
3年前
Java多态实现原理
Java多态概述多态是面向对象编程语言的重要特性,它允许基类的指针或引用指向派生类的对象,而在具体访问时实现方法的动态绑定。Java对于方法调用动态绑定的实现主要依赖于方法表,但通过类引用调用(invokevirtual)和接口引用调用(invokeinterface)的实现则有所不同。类引用调用的大致过程为:Java编译器将Java源代码编译成c
Wesley13 Wesley13
3年前
C++中基类虚析构函数的作用及其原理分析
虚析构函数的理论前提是执行完子类的析构函数,那么父类的虚构函数必然会被执行。那么当用delete释放一个父类指针所实例化的子类对象时,如果没有定义虚析构函数,那么将只会调用父类的析构函数,而不会调用子类的虚构函数,导致内存的泄漏。故: 继承时,要养成的一个好习惯就是,基类析构函数中,加上virtual。知识背景     
Stella981 Stella981
3年前
C++primer学习笔记(六)
1.virtual函数是基类希望派生类重新定义的函数,希望派生类继承的函数不能为虚函数。根类一般要定义虚析构函数。2.派生类只能通过派生类对象访问protected成员,不能用基类对象访问。基类定义为virtual就一直为虚函数,派生类写不写virtual都是虚函数。用做基类的类必须是已定义的。3.存在虚函数指针或引用
Wesley13 Wesley13
3年前
C++基类的析构函数定义为虚函数的原因
1:每个析构函数只会清理自己的成员(成员函数前没有virtual)。2:可能是基类的指针指向派生类的对象,当析构一个指向派生类的成员的基类指针,这时程序不知道这么办,可能会造成内存的泄露,因此此时基类的析构函数要定义为虚函数;基类指针可以指向派生类的对象(多态),如果删除该指针delete\\p,就会调用该指针指向的派生类的析构函数,而派生类
Wesley13 Wesley13
3年前
C++中继承与虚函数
一、类与类之间的关系:1、类与类之间可能会存在共性2、类与类之间必定会有差异3、为了节约开发时间和代码量,我们在设计时可以把类的共项抽象出来形成一个基础类(基类)4、使用基类差异生成一个新的类叫派生类二、继承的语法1、在设计一个类时如果已有的类中有它需要的成员,它可以从已有的类中继承哪些成员,被继承的类叫父类或基类,继承类
Wesley13 Wesley13
3年前
C++多态性与虚函数
  派生一个类的原因并非总是为了继承或是添加新的成员,有时是为了重新定义基类的成员,使得基类成员“获得新生”。面向对象的程序设计真正的力量不仅仅是继承,而且还在于允许派生类对象像基类对象一样处理,其核心机制就是多态和动态联编。(一)多态性  多态是指同样的消息被不同的对象接收时导致不同的行为。所谓消息是指对类成员函数的调用,不同的行为是指的不同的实现