C++基础-关系运算符重载,函数调用运算符重载,字符串类的封装,继承,继承对象模型,继承中的构造和析构函数,继承中的同名处理,继承中静态成员的处理,多继承的概念,菱形继承的概念,虚基类的内部工作

本文详细介绍了C++中的继承机制,包括公有、保护和私有继承,以及构造、析构函数、对象模型、重载运算符(==、!=、函数调用运算符)和静态成员的处理。通过实例演示了如何避免与和或运算符的短路问题,以及如何使用虚继承解决菱形继承问题。
摘要由CSDN通过智能技术生成

01 关系运算符重载

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
using namespace std;

class Person
{
public:
	Person(string name, int age)
	{
		this->m_Age = age;
		this->m_Name = name;
	}

	//==运算符重载(!=运算符重载同理)
	bool operator==(const Person& p)
	{
		if (this->m_Name == p.m_Name && this->m_Age == p.m_Age)
		{
			return true;
		}
		return false;
	}

	bool operator!=(const Person& p)
	{
		if (this->m_Name == p.m_Name && this->m_Age == p.m_Age)
		{
			return false;
		}
		return true;
	}

public:
	string m_Name;
	int m_Age;
};

void test01()
{
	Person p1("小米", 10);
	Person p2("小米", 10);//("小明", 9);

	if (p1 == p2)
	{
		cout << "p1 和 p2 相等" << endl;
	}
	else
	{
		cout << "p1 和 p2 不相等" << endl;
	}

	Person p3("小明", 9);
	if (p3 != p2)
	{
		cout << "p3 和 p2 不相等" << endl;
	}
	else
	{
		cout << "p1 和 p2 相等" << endl;
	}
}

int main(void)
{
	test01();
	system("pause");
	return EXIT_SUCCESS;
}

在这里插入图片描述

02 函数调用运算符重载,不要重载 与和或运算符

1.仿函数

函数调用运算符重载

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
using namespace std;

//()重载
class myPrint
{
public:
	void operator()(string text)
	{
		cout << text << endl;
	}
};

void test01()
{
	myPrint myprint1;
	myprint1("hello world!!");//仿函数
}

在这里插入图片描述

2.函数调用运算符重载匿名对象

class myAdd
{
public:
	int operator()(int val1, int val2)
	{
		return val1 + val2;
	}
};

void test02()
{
	//myAdd myadd;
	//cout << myadd(1, 1) << endl;

	cout << myAdd()(1, 1) << endl;//匿名对象
}

int main(void)
{
	//test01();
	test02();

	system("pause");
	return EXIT_SUCCESS;
}

在这里插入图片描述
由于与和或运算符的短路特性,不要重载 与和或运算符。

03 强化训练-字符串类的封装

MyString.h:

#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
using namespace std;

class MyString
{
	friend ostream& operator<<(ostream& cout, MyString& str);
	friend istream& operator>>(istream& cin, MyString& str);
public:
	//有参构造
	MyString(const char* str);
	//拷贝构造
	MyString(const MyString& str);
	//析构函数
	~MyString();

	//=重载
	MyString& operator=(const MyString& str);
	MyString& operator=(const char* str);

	//[]重载
	char& operator[](int index);

	//+重载
	MyString operator+(const MyString& str);
	MyString operator+(const char* str);

	//==重载
	bool operator==(const MyString& str);
	bool operator==(const char* str);


private:
	char* pString;//指向堆区的指针
	int m_Size;//字符串大小
};
//左移运算符的重载
ostream& operator<<(ostream& cout, MyString& str);
//右移运算符的重载
istream& operator>>(istream& cin, MyString& str);

MyString.cpp:

#include"MyString.h"

MyString::MyString(const char* str)
{
	//cout << "有参构造调用" << endl;
	this->pString = new char[strlen(str) + 1];
	strcpy(this->pString, str);
	this->m_Size = strlen(str);
}

MyString::MyString(const MyString& str)
{
	//cout << "拷贝构造调用" << endl;
	this->pString = new char[strlen(str.pString) + 1];
	strcpy(this->pString, str.pString);
	this->m_Size = str.m_Size;
}

MyString::~MyString()
{
	//cout << "析构函数调用" << endl;
	if (this->pString != NULL)
	{
		delete[] this->pString;
		this->pString = NULL;
	}
}

MyString& MyString::operator=(const MyString& str)
{

	if (this->pString != NULL)
	{
		delete this->pString;
		this->pString = NULL;
	}
	this->pString = new char[strlen(str.pString) + 1];
	strcpy(this->pString, str.pString);
	this->m_Size = str.m_Size;

	return *this;

	// TODO: 在此处插入 return 语句
}

MyString& MyString::operator=(const char* str)
{
	if (this->pString != NULL)
	{
		delete this->pString;
		this->pString = NULL;
	}
	this->pString = new char[strlen(str) + 1];
	strcpy(this->pString, str);
	this->m_Size = strlen(str);

	return *this;
	// TODO: 在此处插入 return 语句
}

char& MyString::operator[](int index)
{
	return this->pString[index];
}

MyString MyString::operator+(const MyString& str)
{
	//计算返回的字符串开辟的大小
	int newSize = this->m_Size + strlen(str.pString) + 1;
	char* tmp = new char[newSize];

	memset(tmp, 0, newSize);
	//拼接字符串
	strcat(tmp, this->pString);
	strcat(tmp, str.pString);

	MyString newStr(tmp);
	delete[] tmp;
	tmp = NULL;

	return newStr;
}

MyString MyString::operator+(const char* str)
{
	//计算返回的字符串开辟的大小
	int newSize = this->m_Size + strlen(str) + 1;
	char* tmp = new char[newSize];

	memset(tmp, 0, newSize);
	//拼接字符串
	strcat(tmp, this->pString);
	strcat(tmp, str);

	MyString newStr(tmp);
	delete[] tmp;
	tmp = NULL;

	return newStr;
}

bool MyString::operator==(const MyString& str)
{
	if (this->m_Size == str.m_Size)
	{
		if (!strcmp(this->pString, str.pString))
		{
			return true;
		}
		return false;
	}
	return false;
}

bool MyString::operator==(const char* str)
{
	if (this->m_Size == strlen(str))
	{
		if (!strcmp(this->pString, str))
		{
			return true;
		}
		return false;
	}
	return false;
}

ostream& operator<<(ostream& cout, MyString& str)
{
	cout << str.pString;
	return cout;
	// TODO: 在此处插入 return 语句
}

istream& operator>>(istream& cin, MyString& str)
{
	//先判断原始是否有内容,如果有的话清空
	if (str.pString != NULL)
	{
		delete str.pString;
		str.pString = NULL;
	}
	//输入内容
	char tep[1024];
	cin >> tep;

	//把输入的内容赋值给str
	str.pString = new char[strlen(tep) + 1];
	strcpy(str.pString, tep);
	str.m_Size = strlen(tep);

	return cin;
	// TODO: 在此处插入 return 语句
}

强化训练-字符串类的封装.cpp:

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include"MyString.h"
using namespace std;

//测试MyString
void test01()
{
	MyString str("abc");

	cout << "str2 = " << str << endl;

	//修改str里面的内容
	/*cout << "请输入str新的内容: " << endl;

	cin >> str;

	cout << "新内容为: " << str << endl;*/

	MyString str2(str);
	
	MyString str3 = "";

	str3 = str2;
	cout << "str2 = " << str2 << "  str3 = " << str3 << endl;
	str2 = "aaaa";
	str3[0] = 'w';
	cout << "str2 = " << str2 << "  str3 = " << str3 << endl;

	cout << "str3 第一个位置为: " << str3[0] << endl;

	MyString str4 = "";
	//字符串拼接
	str4 = str2 + str3;
	str4 = str4 + "bbbb";
	cout << "str4 = " << str4 << endl;

	if (str4 == "aaaawbcbbbb")
	{
		cout << "str4 和 " << "aaaawbcbbbb" << "相等" << endl;
	}
	else
	{
		cout << "str4 和 " << "aaaawbcbbbb" << "不相等" << endl;
	}
	MyString str5 = "";
	str5 = str4;
	if (str4 == str5)
	{
		cout << "str4 和 str5 相等" << endl;
	}
	else
	{
		cout << "str4 和 str5 不相等" << endl;
	}
}

int main(void)
{
	test01();
	system("pause");
	return EXIT_SUCCESS;
}

在这里插入图片描述

04 继承的引出及继承方式

继承:减少代码的重复内容
继承方式:
在这里插入图片描述

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;

class Base1
{
public:
	int m_A;
protected:
	int m_B;
private:
	int m_C;
};

//公有继承
class Son1 :public Base1
{
public:
	void func()
	{
		//cout << m_C << endl;//基类中私有属性,不可继承
		cout << m_A << endl;//基类中公有属性,可继承,还是public
		cout << m_B << endl;//基类中保护属性,可继承,还是protected
	}
};

void myFunc()
{
	Son1 s1;
	s1.m_A;
	//s1.m_B;
}

class Base2
{
public:
	int m_A;
protected:
	int m_B;
private:
	int m_C;
};

//保护继承
class Son2 : protected Base2
{
public:
	void func()
	{
		//cout << m_C << endl;//基类中私有属性,不可继承
		cout << m_A << endl;//基类中公有属性,可继承,还是protected
		cout << m_B << endl;//基类中保护属性,可继承,还是protected
	}
};

void myFunc2()
{
	Son2 s2;
	//s2.m_A; 不可访问
}

class Base3
{
public:
	int m_A;
protected:
	int m_B;
private:
	int m_C;
};

//私有继承
class Son3 : private Base3
{
public:
	void func()
	{
		//cout << m_C << endl;//基类中私有属性,不可继承
		cout << m_A << endl;//基类中公有属性,可继承,还是private
		cout << m_B << endl;//基类中保护属性,可继承,还是private
	}
};

class GrandSon3 :public Son3
{
public:
	void myFunc()
	{
		//孙子类中,访问不到m_A,因为在Son3中m_A已经是私有属性了
		//cout << m_A << endl;
	}
};

05 继承中的对象模型

1.子类中,会继承父类的私有成员,只是被编译给隐藏起来,访问不到私有成员

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;

class Base
{
public:
	int m_A;
protected:
	int m_B;
private:
	int m_C;
};

//子类中,会继承父类的私有成员,只是被编译给隐藏起来,访问不到私有成员
class Son :public Base
{
public:
	int m_D;
};

void test01()
{
	cout << sizeof(Son) << endl;
}

int main(void)
{
	test01();
	system("pause");
	return EXIT_SUCCESS;
}

在这里插入图片描述

2.具体模型查看:

Developer Command Prompt for VS 2022中查看
命令:cl /d1 reportSingleClassLayoutSon test.cpp
在这里插入图片描述

06 继承中的构造和析构函数

1.子类创建对象时,先调用父类的构造,然后调用自己的构造,析构的顺序和构造顺序相反.

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;

class Base
{
public:
	Base()
	{
		cout << "Base默认构造函数调用" << endl;
	}
	~Base()
	{
		cout << "Base析构函数调用" << endl;
	}
};

class Son :public Base
{
public:
	Son()
	{
		cout << "Son默认构造函数调用" << endl;
	}
	~Son()
	{
		cout << "Son析构函数掉哦用" << endl;
	}
};

void test01()
{
	Son s;
}

在这里插入图片描述

2. 如果父类中没有合适的默认构造,那么子类可以利用初始化列表的方式调用父类的其他构造

子类会继承父类的成员属性,成员函数
但是子类不会继承父类的 构造函数 和 析构函数(只有父类自己知道如何构造和析构自己的属性,而子类不知道)

class Base2
{
public:
	Base2(int a)
	{
		this->m_A = a;
		cout << "有参构造函数调用" << endl;
	}
	int m_A;
};

class Son_2 :public Base2
{
public:
	Son_2(int a) :Base2(a)//利用初始化列表的方式调用父类的其他构造
	{

	}
};

void test02()
{
	Son_2 s(10);
	cout << s.m_A << endl;
}

int main(void)
{
	//test01();
	test02();
	system("pause");
	return EXIT_SUCCESS;
}

在这里插入图片描述

07 继承中的同名处理

1.想调用父类中的属性

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;

class Base
{
public:

	Base()
	{
		this->m_A = 100;
	}

	int m_A;
};

class Son :public Base
{
public:
	Son()
	{
		this->m_A = 200;
	}
	int m_A;
};

void test01()
{
	Son s;
	cout << s.m_A << endl;

	//调用父类中的m_A
	cout << s.Base::m_A << endl;
}

int main(void)
{
	test01();
	system("pause");
	return EXIT_SUCCESS;
}

在这里插入图片描述
对象模型:
在这里插入图片描述

2.子类和父类的成员函数的名称相同,子类会把父类所有的同名版本都隐藏掉

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;

class Base
{
public:

	Base()
	{
		this->m_A = 100;
	}

public:

	void func()
	{
		cout << "Base中的func的调用" << endl;
	}
	void func(int a)
	{
		cout << "Base中的func(int a)的调用" << endl;
	}

	int m_A;
};

class Son :public Base
{
public:
	Son()
	{
		this->m_A = 200;
	}
public:
	void func()
	{
		cout << "Son中的func调用" << endl;
	}
	int m_A;
};

//如果子类和父类拥有同名的成员属性和函数,子类不会覆盖父类的成员
//如果子类和父类的成员函数的名称相同,子类会把父类所有的同名版本都隐藏掉
//想调用父类的方法,必须加作用域
void test01()
{
	Son s;
	cout << s.m_A << endl;

	//打印父类中的m_A
	cout << s.Base::m_A << endl;

	//调用Son中的func
	s.func();

	//调用Base中的func
	s.Base::func();

	//调用Base中的func(int a)
	//s.func(10);//子类和父类的成员函数的名称相同,子类会把父类所有的同名版本都隐藏掉
	s.Base::func(10);
}

int main(void)
{
	test01();

	system("pause");
	return EXIT_SUCCESS;
}

在这里插入图片描述

08 继承中静态成员的处理

类似继承中的同名处理

//类似继承中的同名处理
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;

class Base
{
public:
	static void func()
	{
		cout << "Base 的func()调用 " << endl;
	}

	static void func(int a)
	{
		cout << "Base 的func(int)调用 " << endl;
	}

	static int m_A;
};
int Base::m_A = 20;

class Son :public Base
{
public:
	static int m_A;

	static void func()
	{
		cout << "Son 中的func() 的调用" << endl;
	}
};
int Son::m_A = 10;


//静态成员属性 子类可以继承下来
void test01()
{
	cout << Son::m_A << endl;

	cout << Base::m_A << endl;

	Son::func();

	Son::Base::func(10);
	Base::func();
}

int main(void)
{
	test01();
	system("pause");
	return EXIT_SUCCESS;
}

在这里插入图片描述

09 多继承的概念以及问题

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;

class Base1
{
public:
	Base1()
	{
		m_A = 10;
	}
	int m_A;
};

class Base2
{
public:
	Base2()
	{
		m_A = 20;
	}
	int m_A;
};

//多继承
class Son :public Base1, public Base2
{
public:
	int m_C;
	int m_D;
};

void test01()
{
	cout << sizeof(Son) << endl;

	Son s1;
	//cout << s1.m_A << endl; //如果Base2中有m_A,会有二义性
	cout << s1.Base1::m_A << endl;
	cout << s1.Base2::m_A << endl;
}

int main(void)
{
	test01();
	system("pause");
	return EXIT_SUCCESS;
}

在这里插入图片描述
对象模型:
在这里插入图片描述

10 菱形继承的概念以及问题

在这里插入图片描述

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;

class Animal
{
public:

	int m_Age;

};

class Sheep :public Animal
{
public:


};

class Tuo :public Animal
{
public:

};

class SheepTuo :public Sheep, public Tuo
{
public:

};

//菱形继承的解决 利用虚继承
void test01()
{
	SheepTuo sp;
	sp.Sheep::m_Age = 10;
	sp.Tuo::m_Age = 20;

	cout << sp.Sheep::m_Age << endl;
	cout << sp.Tuo::m_Age << endl;
	//cout << sp.m_Age << endl;//二义性
}

int main(void)
{
	test01();
	system("pause");
	return EXIT_SUCCESS;
}

在这里插入图片描述
对象模型:
在这里插入图片描述
菱形继承的解决,利用虚继承

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;

class Animal
{
public:

	int m_Age;

};

//虚基类 Sheep
class Sheep :virtual public Animal
{
public:


};

//虚基类 Tuo
class Tuo :virtual public Animal
{
public:


};

class SheepTuo :public Sheep, public Tuo
{
public:


};

//菱形继承的解决 利用虚继承
//操作的是共享的一份数据
void test01()
{
	SheepTuo sp;
	sp.Sheep::m_Age = 10;
	sp.Tuo::m_Age = 20;

	cout << sp.Sheep::m_Age << endl;
	cout << sp.Tuo::m_Age << endl;

	cout << sp.m_Age << endl;//可以直接访问,已经没有二义性的可能了,重复数据只有一份

}

int main(void)
{
	test01();
	system("pause");
	return EXIT_SUCCESS;
}

在这里插入图片描述
vbptr:virtual base pointer
对象模型:
在这里插入图片描述

11 虚基类的内部工作原理解析

找到Sheep的偏移量操作:
(int )&st :取地址改成int,改变步长
*(int *)&st :找到下面的虚基列表
(int (int *)&st :虚基列表的步长
(int (int *)&st+1:找到Seep的虚基列表的1位置
*((int (int *)&st+1):取到8

找到Tuo的偏移量操作:
((int)&st+1):找到4的位置 :base class Tuo

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;

class Animal
{
public:

	int m_Age;

};

//虚基类 Sheep
class Sheep :virtual public Animal
{
public:


};

//虚基类 Tuo
class Tuo :virtual public Animal
{
public:


};

class SheepTuo :public Sheep, public Tuo
{
public:


};

//菱形继承的解决 利用虚继承
void test01()
{
	SheepTuo sp;
	sp.Sheep::m_Age = 10;
	sp.Tuo::m_Age = 20;

	cout << sp.Sheep::m_Age << endl;
	cout << sp.Tuo::m_Age << endl;

	cout << sp.m_Age << endl;//可以直接访问,已经没有二义性的可能了,重复数据只有一份

}

//通过地址找到偏移量
//内部工作原理
void test02()
{
	SheepTuo st;
	st.m_Age = 100;

	//找到Sheep的偏移量操作
	cout << *(int *)((int *)*(int *)&st + 1)<< endl;

	//找到Tuo的偏移量操作
	cout << *(int*)((int*)*((int*)&st +1) + 1) << endl;

	//输出age
	cout << ((Animal*)(char*)&st + *(int*)((int*)*(int*)&st + 1))->m_Age << endl;
}

int main(void)
{
	test02();
	system("pause");
	return EXIT_SUCCESS;
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值