首页 > 编程语言 >施磊c++基础7

施磊c++基础7

时间:2024-10-22 21:20:26浏览次数:3  
标签:cout int 基础 c++ class cast data public 施磊

C++的四种类型转换

c语言中提供的类型强转

int a = (int)b;

c++提供:

  1. const_cast:去掉常量属性的一个类型转换
	int* p1 = (int*)&a;
	int* p2 = const_cast<int*>(&a);

这两句是一样的,只不过使用第二种,可以保证类型转换是安全的,如果要转换成不符合的类型就会报错。

  1. static_cast:提供编译器认为安全的类型转换
int main()
{
	//1
	int a = 10;
	char b = static_cast<int> (a);
	//2
	int* p = nullptr;
	short* b = static_cast<short*>(p);
	return 0;
}

对于第一种,int转char,编译器认为是安全的,就可以通过
对于第二章,int转成short,编译器认为类型转换无效
那么如果我一定要做这种类型转换呢?那么就是下面的reinterpret_cast

  1. reinterpret_cast:类似c风格的强制类型转换(不安全)
	int *p = nullptr;
	double* b = reinterpret_cast<double*>(p);

即使实际上这种转换并不安全,但也可以编译成功

  1. dynamic_cast:主要用在继承结构中,可以支持RTTI类型识别上下转换

示例代码:

#include<iostream>
using namespace std;

class Base {
public:
	virtual void func() = 0;
};

class Derive1 :public Base
{
public:
	virtual void func() { cout << "Derive -- 1" << endl; }
};

class Derive2 :public Base
{
public:
	virtual void func() { cout << "Derive -- 2" << endl; }
};

void showFunc(Base* p)
{
	p->func();//动态绑定
}
int main()
{
	Derive1  d1;
	Derive2  d2;
	showFunc(&d1);
	showFunc(&d2);
	return 0;
	//Derive -- 1
	//Derive -- 
}

没有问题

但是随着软件开发的需求变更,要增加需求
在Derive2中添加一个函数

class Derive2 :public Base
{
public:
	void func() { cout << "Derive -- 2" << endl; }
	void showFunc{
		cout << "new 2" << endl;
	}
};

现在我要在showFunc中,其他的依旧动态绑定func()函数
而如果是Derive2对象,就要绑定新的showFunc()函数

使用

void showFunc(Base* p)
{
	// dynamic_cast会检查p指针是否指向的是一个Derive2类型的对象。
	//p->vfptr->vftable RTTI信息,如果是Derive2类型的对象
	//转换类型成功---返回Derive2对象的地址给pd2;否则返回nullptr
	Derive2* pd2 = dynamic_cast<Derive2*>(p);

	if (pd2 != nullptr)
	{
		pd2->derive02func();
	}
	else {
		p->func();//动态绑定
	}
}
理解虚基类和虚继承

抽象类(有纯虚函数的类) / 虚基类
virtual

  1. 修饰成员方法是虚函数
  2. 可以修饰继承方式,是虚继承。被继承的类称为虚基类
#include<iostream>
using namespace std;

class A
{
public:
private:
	int ma;
};

class B :virtual public A
{
public:

private:
	int mb;
};

/*
A a:4字节  ma ---》4字节 ma
B b:8字节 ma,mb ---》12字节 vbptr, mb ,ma
*/
int main()
{
	
}

在这里插入图片描述

class A{}; sizeof(A) = 1

class B :public A{};sizeof(B) = 1;

class A {
virtual void fun(){};
};
class B :public A{};sizeof(B) = 4;//vfptr

class A {
virtual void fun(){};
};
class B :virtual public A{};sizeof(B) = 8;//vbptr + vfptr

基类指针指向派生类对象,永远指向的是派生类基类部分数据的起始地址
在这里插入图片描述
由于内存结构*p指向的是派生类基类部分数据的起始地址D8,但是vbptr和mb都还在前面,这时候delete p;就会导致前面的删不掉

菱形继承问题

多重继承:代码的复用 ---- 一派生类有多个基类

菱形继承问题

class D:public B,public C
{
};

在这里插入图片描述
一目了然:D中有两份来自不同父类的ma属性
尽量不要多重继承

实例代码:

#include<iostream>
using namespace std;

class A
{
public:
	A(int data) :ma(data) { cout << "A()" << endl; }
	~A() { cout << "~A()" << endl; }
protected:
	int ma;
};
//===================================================
class B : public A
{
public:
	B(int data) :A(data), mb(data) { cout << "B()" << endl; }
	~B() { cout << "~B()" << endl; }
protected:
	int mb;
};

class C : public A
{
public:
	C(int data) :A(data), mc(data) { cout << "C()" << endl; }
	~C() { cout << "~C()" << endl; }
protected:
	int mc;
};
//===================================================
class D : public B,public C
{
public:
	D(int data):B(data), C(data),md(data) { cout << "D()" << endl; }
	~D() { cout << "~D()" << endl; }
protected:
	int md;
};
int main()
{
	D d(10);
	
}

d的内存布局 ---- 占20字节
在这里插入图片描述
打印结果:
在这里插入图片描述
此时只要在B,C中对A采用虚继承,就可以了。内存结构如下

在这里插入图片描述
注意:此时需要在D中加入A的构造,即使从继承类看,他并没有直接继承A。但是由于B,C都是虚继承,此时A的构造就要定位到D中对A进行构造;

具体如下:

class D : public B,public C
{
public:
	D(int data):A(data),B(data), C(data),md(data) { cout << "D()" << endl; }
	~D() { cout << "~D()" << endl; }
protected:
	int md;
};

标签:cout,int,基础,c++,class,cast,data,public,施磊
From: https://blog.csdn.net/fcopy/article/details/143063467

相关文章

  • 【C++指南】类和对象(四):类的默认成员函数——全面剖析 : 拷贝构造函数
     引言拷贝构造函数是C++中一个重要的特性,它允许一个对象通过另一个已创建好的同类型对象来初始化。了解拷贝构造函数的概念、作用、特点、规则、默认行为以及如何自定义实现,对于编写健壮和高效的C++程序至关重要。 C++类和对象系列文章,可点击下方链接阅读:【C++指南......
  • PTA 生成格雷码 | C++ | 二叉树
    格雷码是一种包含2n个数串的序列,这种序列:1不存在重复的元素,2每个元素都是长度为n的二进制数串,3相邻元素只有一位不同。例如,长度为23的格雷码为:000,001,011,010,110,111,101,100。请使用分治法构造格雷码。提示,使用分治法构造格雷码,详见百度百科。输入格式:输入一个正整数n(1<=......
  • 贪吃蛇编译就能玩c++
    #include<stdio.h>#include<conio.h>#include<iostream>#include<stdlib.h>#include<windows.h>#include<time.h>#defineframex2#defineframey2#definewide40#definehigh25usingnamespacestd;inti,a[2];intj=......
  • 代码随想录算法训练营 | 图论理论基础,98. 所有可达路径
    图论理论基础1.图的种类:有向图,无向图,加权有向图,加权无向图;2.度:无向图中有几条边连接该节点,该节点就有几度,在有向图中,每个节点有出度和入度;出度:从该节点出发的边的个数;入度:指向该节点边的个数;3.连通图:在无向图中,任何两个节点都是可以到达的;强连通图:在有向图中,任何两个节点是可以......
  • 2024版最新大模型场景应用汇总(持续更新)零基础入门到精通,收藏这篇就够了
    一、应用场景1.办公场景智能办公:文案生成(协助构建大纲+优化表达+内容生成)、PPT美化(自动排版+演讲备注+生成PPT)、数据分析(生成公式+数据处理+表格生成)。智能会议:会议策划(生成会议环节+会议分论坛+会议时间+会议预算)、同声传译(实时的多语言互译)、会议记录(生成结构清明+要......
  • JZOJ【基础】素数密码学//注意:后面有彩蛋
    VIP以下是一个C++程序,该程序接受一个合数n作为输入,并尝试将其分解为两个素数的乘积。如果成功找到这样的分解,它将输出所有可能的分解方式;如果找不到,它将输出"error"。#include<bits/stdc++.h>usingnamespacestd;boolisPrime(intnum){if(num<=1){ returnfa......
  • Python基础学习目录
    Python学习目录Python自动化第一周Python自动化第二周Python文件的操作Python函数的进阶Python装饰器Python函数基础Python深浅copyPython迭代器、生成器Python推导式Python内置函数及匿名函数Python递归及二分查找算法Python面向对象(基础篇)Pytho......
  • c++ STL标准模板库-算法
    C++StandardTemplateLibrary(STL)算法是一组泛型算法,它们可以在各种容器上操作。这些算法被设计为与容器无关,因此可以在任何提供必要迭代器接口的容器上使用。STL算法分为以下几个主要类别:非修改算法Non-modifyingsequenceoperations:不改变容器内容,主要用于搜索和排序。......
  • c++时间管理大师
    作者花了一个下午写出来的。c++写的时间管理大师。支持一下。#include<bits/stdc++.h>#include<windows.h>usingnamespacestd;constintpai=250;constintban=pai/2;#defineD1262#defineD2294#defineD3330#defineD4349#defineD5392#defineD6440......
  • 使用 C++ 实现网络编程 NetWork(pro版)
    上一次小编分享了C++实现网络编程NetWork,这是链接:C++网络通信类Network的实现详解-CSDN博客这次小编带着改进之后的NetWork归来!在现代计算机网络中,网络通信是不可或缺的一部分。本文将介绍如何使用C语言实现一个简单的网络通信库,涵盖TCP和UDP协议的基本功能。我们将通过......