当前位置: 首页 > 编程笔记 >

C++ 基类指针和子类指针相互赋值的实现方法

邵浩大
2023-03-14
本文向大家介绍C++ 基类指针和子类指针相互赋值的实现方法,包括了C++ 基类指针和子类指针相互赋值的实现方法的使用技巧和注意事项,需要的朋友参考一下

首先,给出基类animal和子类fish

//============================================================== 
//   animal.h 
// 
// author : zwq 
// describe: 非虚函数情况下,将子类指针赋给积累指针,验证最终调用 
//   基类函数还是子类函数。 
//============================================================== 
#ifndef ANIMAL_H 
#define ANIMAL_H 
 
//=============================================================== 
// 
//    animal 
//    动物基类 
// 
//=============================================================== 
class animal 
{ 
public: 
 void breathe();  // 非虚函数 
}; 
 
//=============================================================== 
// 
//      animal 
//    鱼类,集成于动物基类 
// 
//=============================================================== 
class fish : public animal 
{ 
public: 
 void breathe();  // 非虚函数 
}; 
 
#endif 
#include "StdAfx.h" 
#include <iostream> 
#include "Animal.h" 
 
using namespace std; 
 
//=============================================================== 
// 
//    animal 
//    动物基类 
// 
//=============================================================== 
 
void animal::breathe() 
{ 
 cout << "animal breathe" << endl; 
} 
 
//=============================================================== 
// 
//      animal 
//    鱼类,集成于动物基类 
// 
//=============================================================== 
 
void fish::breathe() 
{ 
 cout << "fish bubble" << endl; 
} 

一. 基类指针和子类指针之间相互赋值

(1)将子类指针赋值给基类指针时,不需要进行强制类型转换,C++编译器将自动进行类型转换。因为子类对象也是一个基类对象。

(2)将基类指针赋值给子类指针时,需要进行强制类型转换,C++编译器将不自动进行类型转换。因为基类对象不是一个子类对象。子类对象的自增部分是基类不具有的。

执行以下代码,看看会报什么错误:

int main(int argc, char* argv[]) 
{ 
 ExamAnimal(); 
 
 return 0; 
} 
 
void ExamAnimal() 
{ 
 // 将子类指针直接赋给基类指针,不需要强制转换,C++编译器自动进行类型转换 
 // 因为fish对象也是一个animal对象 
 animal* pAn; 
 fish* pfh = new fish; 
 pAn = pfh; 
  
 delete pfh; 
 pfh = NULL; 
  
 // 将基类指针直接赋给子类指针,需要强制转换,C++编译器不会自动进行类型转换 
 // 因为animal对象不是一个fish对象 
 fish* fh1; 
 animal* an1 = new animal; 
 // 没有进行强制类型转化 
 fh1 = an1; 
 
 delete an1; 
 an1 = NULL; 
} 

编译时,报如下错误信息:

--------------------Configuration: CPlusPlusPrimer - Win32 Debug-------------------- Compiling... CPlusPlusPrimer.cpp E:\Study\example\CPlusPlusPrimer\CPlusPlusPrimer.cpp(94) : error C2440: '=' : cannot convert from 'class animal *' to 'class fish *' Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast Error executing cl.exe.

CPlusPlusPrimer.exe - 1 error(s), 0 warning(s)

根据以上错题提示信息,对代码做如下修改:

void ExamAnimal() 
{ 
 // 将子类指针直接赋给基类指针,不需要强制转换,C++编译器自动进行类型转换 
 // 因为fish对象也是一个animal对象 
 animal* pAn; 
 fish* pfh = new fish; 
 pAn = pfh; 
  
 delete pfh; 
 pfh = NULL; 
  
 // 将基类指针直接赋给子类指针,需要强制转换,C++编译器不会自动进行类型转换 
 // 因为animal对象不是一个fish对象 
 fish* fh1; 
 animal* an1 = new animal; 
 // 修改处: 
 // 进行强制类型转化 
 fh1 = (fish*)an1; 
 
 delete an1; 
 an1 = NULL; 
} 

再次编译,通过。

二. 子类指针赋给基类指针时内存分析

(1)int变量赋给char变量

整型int转换为char类型时,只有一个字节的内容能够放进char类型,剩下的三个字节内容放不下,被截掉,丢失精度。 两个变量或者对象进行转换时,一定要看两者的内存模型是否互相匹配。

(2)子类fish指针赋给基类animal指针

下面看看子类fish指针赋给基类animal指针时,内存的变化: 当我们构造fish类的对象时,首先要调用animal类的构造函数去构造animal类的构造函数,然后才调用fish类的构造函数完成自身部分的构造,从而拼接出一个完整的fish对象。当我们将fish类对象转换为animal类对象时,该对象就被认为是原对象整个内存模型的上半部分,也就是图中animal对象的内存部分。当我们利用类型转换后的对象指针去调用它的方法时,自然是调用它所在的内存中的方法。 在这里,animal类对象类似于char类型的对象,fish类对象类似于int类型的对象,将fish类对象赋给animal类对象时,会截取fish类对象自身的部分,剩下fish类对象中的animal部分。

(3)基类animal指针赋给子类fish指针

基类animal对象包含的信息少,类fish对象包含的信息多,将信息少的对象直接转换为信息多的对象时(没有强制类型转换),显然是无法构造出多出的信息。在编译时,也会发生如下错误:error C2440: '=' : cannot convert from 'class animal *' to 'class fish *'。 这时,需要做强制类型转换:

// 将基类指针直接赋给子类指针,需要强制转换,C++编译器不会自动进行类型转换 
// 因为animal对象不是一个fish对象 
fish* fh1; 
animal* an1 = new animal; 
// 进行强制类型转化 
fh1 = (fish*)an1; 

以上就是小编为大家带来的C++ 基类指针和子类指针相互赋值的实现方法全部内容了,希望大家多多支持小牛知识库~

 类似资料:
  • 问题内容: 根据这个问题的回答 关于指针与接收器的值的规则是,可以在指针和值上调用值方法,但是只能在指针上调用指针方法 但实际上我可以对非指针值执行指针方法: 那么,这是怎么了?这是新功能吗?还是对问题的回答是错误的? 问题答案: 您正在对指针值调用“指针方法”。在表达式中: 是类型(非指针);由于该方法具有指针接收者,并且由于接收者值是非指针且可寻址,因此它是以下各项的简写形式: 这是在规范中:

  • C++ 类 & 对象 一个指向 C++ 类的指针与指向结构的指针类似,访问指向类的指针的成员,需要使用成员访问运算符 ->,就像访问指向结构的指针一样。与所有的指针一样,您必须在使用指针之前,对指针进行初始化。 下面的实例有助于更好地理解指向类的指针的概念: #include <iostream> using namespace std; class Box { public:

  • 公有派生类的对象可作为其相应基类的对象处理,这使得一些有意义的操作成为可能。例如,从某个特定基类派生出来的各种类,尽管这些类的对象彼此之间互不相同,但是仍然能够建立这些对象的链表,只要把这些对象作为基类对象处理就可以了。然而反过来是不行的,基类的对象不能自动成为派生类的对象。 常见编程错误 9.1 将基类对象作为派生类对象处理。 程序员可以用显式类型转换把基类指针强制转换为派生类指针。但是,如果要

  • 问题内容: 我是Java菜鸟。我已经掌握了将C / C ++指针转换为Java引用的概念,并且进展相当顺利。 我打了一段有指针的代码(即* ptr)。我需要取消引用指针并更改其指向的指针的值(即 ptr =&newthing;) 在Java中这似乎要困难得多。是否有人对如何解决此问题有任何想法?快速谷歌搜索什么都没有。 这是C ++中的代码示例。我想在Java中获得类似的工作,但是ptr_to_p

  • 学习 C++ 的指针既简单又有趣。通过指针,可以简化一些 C++ 编程任务的执行,还有一些任务,如动态内存分配,没有指针是无法执行的。所以,想要成为一名优秀的 C++ 程序员,学习指针是很有必要的。 正如您所知道的,每一个变量都有一个内存位置,每一个内存位置都定义了可使用连字号(&)运算符访问的地址,它表示了在内存中的一个地址。请看下面的实例,它将输出定义的变量地址:#include <iostr

  • 但我想使用一个指针,而不是一个简单的变量。能给我点启示吗? 谢谢

  • 指针变量也是变量,是变量就可以任意赋值,不要越界即可(32位编译器指针大小为4字节,64位编译器指针大小为8字节),但是,任意数值赋值给指针变量没有意义,因为这样的指针就成了野指针,此指针指向的区域是未知(操作系统不允许操作此指针指向的内存区域)。所以,野指针不会直接引发错误,操作野指针指向的内存区域才会出问题。 int a = 100; int *p; p = a; //把a的值赋值给指针变量p

  • 指针可以指向一份普通类型的数据,例如 int、double、char 等,也可以指向一份指针类型的数据,例如 int *、double *、char * 等。 如果一个指针指向的是另外一个指针,我们就称它为 二级指针,或者 指向指针的指针。 假设有一个 int 类型的变量 a,p1是指向 a 的指针变量,p2 又是指向 p1 的指针变量,它们的关系如下图所示: 将这种关系转换为C语言代码: 指针变