C++中基类和派生类之间的转换实例教程

 更新时间:2014年08月23日 10:07:20   投稿:shichen2014  
这篇文章主要介绍了C++中基类和派生类之间的转换,有助于深入理解C++面向对象程序设计,需要的朋友可以参考下

本文实例讲解了C++中基类和派生类之间的转换。对于深入理解C++面向对象程序设计有一定的帮助作用。此处需要注意:本文实例讲解内容的前提是派生类继承基类的方式是公有继承,关键字public。具体分析如下:

以下程序为讲解示例:

#include<iostream>
using namespace std;

class A
{
public:
  A(int m1, int n1):m(m1), n(n1){}
  void display();
private:
  int m;
  int n;
};

void A::display()
{
  cout << "m = " << m << endl;
  cout << "n = " << n << endl;
}

class B :public A
{
public:
  B(int m1, int n1, int p1) :A(m1, n1), p(p1){}
  void display();
private:
  int p;
};

void B::display()
{
  A::display();
  cout << "p = " << p << endl;
}

void print1(A& a)
{
  a.display();
}

void print2(B& b)
{
  b.display();
}

void print3(A a)
{
  a.display();
}

void print4(B b)
{
  b.display();
}

int main()
{
  A a(3, 4);
//  a.display();
  B b(10, 20, 30);
//  b.display();

  A * pa;
  B * pb;
  pa = &a;
//  pa->display();
  pb = &b;
//  pb->display();

//  pa = &b;
//  pa->display();

//  pb = &a;       //错误。派生类指针不能指向基类对象。

//  print1(b);
//  print2(a);      //错误。不能用基类对象给派生类引用赋值。
//  print3(b);
//  print4(a);      //错误。不能用基类对象给派生类对象赋值。

//  pb = pa;       //不能用基类指针给派生类指针赋值。

  pb = (B*)pa;     //可以强制转换,但是非常不安全。
  pb->display();    //出现安全问题,p无法访问,因为a中没有p成员
  system("pause");
  return 0;
}

切记:派生类对象是基类对象,派生类中包含有基类的成员。基类对象不是派生类对象,它不能包含派生类型的成员。

一、派生类到基类的转化

1.派生类对象地址赋值给基类指针

main函数中执行以下代码

A a(3, 4);
//  a.display();
  B b(10, 20, 30);
//  b.display();

  A * pa;
//  B * pb;
//  pa = &a;
//  pa->display();
//  pb = &b;
//  pb->display();

  pa = &b;
  pa->display();     //会输出 10 20

pa为基类指针,指向派生类对象是合法的,因为派生类对象也是基类对象。语句会输出派生类对象中基类部分。

注意:这里并不会调用派生类的display函数,调用的是基类的display函数,因为指针pa是基类指针,编译器在编译阶段只知道pa的类型。如果要实现调用派生类的display函数,需要用到虚函数实现多态性。之后的文章会讲到。

进一步解释一下编译时和运行时的区别。

编译时编译器能知道pa的类型为A *,但是不知道它指向了哪个对象,假如有以下语句

A a(3, 4);
B b(10, 20, 30);
A* pa;
int number;
cin >> number;
if (number >= 0)
  pa = &a;
else
  pa = &b;

pa指向的对象类型依赖于输入,运行时才输入,所以编译器是没有办法知道pa指向哪个类型的。

2.派生类对象赋值给基类引用

引用跟指针基本没有区别,引用本质上是指针,是个指针常量,具体可以参照我的另一篇C++中的引用和指针的联系和区别

main函数中执行以下代码

A a(3, 4);
B b(10, 20, 30);
print1(b);      //会输出 10 20

形参为基类引用,实参为派生类对象,派生类对象也是基类对象,可以赋值给基类引用。输出派生类中基类部分。

注意:此时对象本身并未复制,b仍然是派生类对象,前面说过了引用就是一个指针

3.派生类对象赋值给基类对象。

A a(3, 4);
B b(10, 20, 30);
print3(b);

派生类对象基类部分被复制给形参。

注意:实际上没有从派生类对象到基类对象的直接转换。对基类对象的赋值或初始化,实际上在调用函数,初始化时调用构造函数,赋值时调用赋值操作符。

二、基类到派生类的转化

切记:这种转换有可能引发严重的安全问题,编写代码时不要使用。没有基类到派生类的自动转换,原因在于基类对象只能是基类对象,不能包含派生类型的成员

如果允许用基类对象给派生类对象赋值,那么就可以试图使用该派生类对象访问不存在的成员。

A a(3, 4);
B b(10, 20, 30);
A * pa;
B * pb;
//  print2(a);      //错误。不能用基类对象给派生类引用赋值。
//  print4(a);      //错误。不能用基类对象给派生类对象赋值。
//  pb = &a;       //错误。派生类指针不能指向基类对象。

pa = &a;
pb = &b;

//pb = pa;           //错误。不能用基类指针给派生类指针赋值。

pb = (B*)pa;     //可以强制转换,但是非常不安全。
pb->display();    //出现安全问题,p无法访问,因为a中没有p成员

注意到我们使用强制转换时,当派生类添加了基类中不存在的成员时,会出现安全问题。

pb->display();会调用派生类的display函数,但是它指向的内存是基类对象a的内存,p不存在。会出现严重后果。

相关文章

  • VS编译出现MSB3073命令的解决方案

    VS编译出现MSB3073命令的解决方案

    =error MSB3073是Visual Studio编译器报出的错误,本文主要介绍了VS编译出现MSB3073命令的解决方案,具有一定的参考价值,感兴趣的可以了解一下
    2023-09-09
  • C++实现String类实例代码

    C++实现String类实例代码

    这篇文章主要介绍了C++实现String类实例代码的相关资料,需要的朋友可以参考下
    2017-04-04
  • C语言关于注释的知识点总结

    C语言关于注释的知识点总结

    在本篇文章里小编给大家分享的是关于C语言关于注释的知识点总结,需要的朋友们可以参考学习下。
    2020-02-02
  • C# CLR 中学习 C++关键词extern使用详解

    C# CLR 中学习 C++关键词extern使用详解

    这篇文章主要为大家介绍了C# CLR 中学习 C++ 之extern使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-09-09
  • C++实现日期计算器详细代码示例

    C++实现日期计算器详细代码示例

    这篇文章主要给大家介绍了关于C++实现日期计算器的相关资料,基于C++编写的简单的日期计算器,供大家参考,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-03-03
  • C语言实现动态爱心代码

    C语言实现动态爱心代码

    这篇文章主要为大家详细介绍了如何通过C语言实现动态爱心的效果,文中的示例代码讲解详细,具有一定的学习价值,还不快跟随小编一起get李峋同款爱心代码
    2022-11-11
  • VSCode插件开发全攻略之package.json详解

    VSCode插件开发全攻略之package.json详解

    这篇文章主要介绍了VSCode插件开发全攻略之package.json的相关知识,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-05-05
  • C++类型转换和IO流操作处理教程

    C++类型转换和IO流操作处理教程

    这篇文章主要给大家介绍了关于C++类型转换和IO流操作处理的相关资料,标准C++为了加强类型转换的可视性,引入了四种命名的强制类型转换操作符,文中给出了详细的代码示例,需要的朋友可以参考下
    2023-08-08
  • 基于C++自制屠夫躲猫猫小游戏

    基于C++自制屠夫躲猫猫小游戏

    这篇文章主要为大家详细介绍了如何基于C++自制屠夫躲猫猫小游戏,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2024-01-01
  • 详解C++语言中的加法运算符与赋值运算符的用法

    详解C++语言中的加法运算符与赋值运算符的用法

    这篇文章主要介绍了C++语言中的加法运算符与赋值运算符的用法,是C++入门学习中的基础知识,需要的朋友可以参考下
    2016-01-01

最新评论