C++自学笔记小记(十一_二)(黑马)

面向对象编程自学笔记整理

十一_二、类与对象

3、对象模型和this指针

/*******************1.成员变量和成员函数分开储存******************************/
//#include<iostream>
//using namespace std;
//
//class person
//{
//	int m_A;//非静态成员变量,属于类的对象上
//	
//	static int m_B;//静态成员变量(类内声明).不属于类的对象上
//	
//	void func(){}//非静态成员函数,不属于类的对象上
//	
//	static void func2() {}//静态成员函数,不属于类的对象上
//};
//int person::m_B=0;//静态成员变量(类外初始化)
//
//
//void test01()
//{
//	//空对象所占的内存空间为:1
//	//C++编译器会给每一个空对象分配一个字节的空间,为了区分空对象占内存的位置
//	//每个空对象也应该有一个独一无二的内存空间
//	person p;
//	cout << "sizeof(p)=" << sizeof(p) << endl;
//}
//
//void test02()
//{
//	person p;
//	cout << "sizeof(p)=" << sizeof(p) << endl;
//}
//int main()
//{
//	//test01();
//	test02();
//	system("pause");
//	return 0;
//}

/*******************2.this指针******************************/
//#include<iostream>
//using namespace std;
//
this 指针的用途
当形参和成员变量同名时,可用this指针来区分
在类的非静态成员函数中返回 对象本身,可用return *this
//class person
//{
//public:
//	person(int age)//构造函数
//	{
//		//this指针指向被调用的成员函数 所属的对象
//		this->age = age;
//	}
//	//值的方式返回,会创建一个新的对象
//	//引用的方式返回,不会创建一个新对象,会一直返回p2
//	person& personaddage(person &p)
//	{
//		this->age += p.age;
//		//this指向p2的指针,*this指向的就是p2的本体
//		return *this;
//	}
//	int age;
//
//};
1解决名称冲突
//void test01()
//{
//	person p1(18);
//	cout << "p1年龄为:" << p1.age << endl;
//}
//
2返回对象本身用*this
//void test02()
//{
//	person p1(10);
//	person p2(10);
//	//链式编程思想
//	p2.personaddage(p1).personaddage(p1).personaddage(p1);
//	cout << "p2的年龄为:" << p2.age << endl;
//}
//
//int main()
//{
//	//test01();
//	test02();
//	system("pause");
//	return 0;
//}


/*******************3.空指针调用成员函数******************************/
//#include<iostream>
//using namespace std;
//
//class person
//{
//public:
//	void showclassName()
//	{
//		cout << "this is person class" << endl;
//	}
//	void showpersonAge()
//	{
//		//报错原因是传入的指针为空指针NULL
//		if (this == NULL)
//		{
//			return;
//		}//提高代码的鲁棒性
//		cout << "age=" << this->m_age << endl;
//	}
//	int m_age;
//};
//
//void test01()
//{
//	person* p = NULL;//创建一个空指针
//	//p->showclassName();
//	p->showpersonAge();
//}
//int main()
//{
//	test01();
//	system("pause");
//	return 0;
//}

/*******************4.const修饰成员函数******************************/
//#include<iostream>
//using namespace std;
//
const修饰的为只读函数或者只读变量
//
常函数
成员函数后面加const我们称这个函数为常函数
常函数不可以修改成员属性
成员属性声明时加关键字mutable后,在常函数中依旧可以修改
常函数
//class person
//{
//public:
//	//this指针的本质:指针常量 指针指向不可以修改
//	//person *const this;(指针常量)--指针指向不可以修改
//	//const person *const this;指针的指向和指针指向的值都不可以修改 
//	//在成员函数后面加上const,修饰的是this指向,让指针指向的值也不可以修改
//	
//	void showperson() const//常函数
//	{
//		this->m_b = 100;
//		//this->m_a = 100;//this指针指向的值也不可以修改
//		//this = NULL;//this指针的指向不可以修改
//	}
//	void func()//普通函数
//	{
//		m_a = 100;
//	}
//	int m_a;
//	mutable int m_b;//特殊变量,在常函数中也可以修改值,加关键字mutable
//};
//
//void test01()
//{
//	person p;
//	p.showperson();
//}
//
常对象
声明对象前加const称该对象为常对象
常对象只能调用常函数
常对象
//void test02()
//{
//	const person p;//在对象前加const就是一个常对象
//	//特点:不能修改指针指向的值
//	//p.m_a = 100;
//	p.m_b = 100;//特殊变量,在常对象中也可以修改值,加关键字mutable
//	//常函数只能调用常对象	
//	p.showperson();//常对象可以调用常函数
//	//p.func();//常对象不能调用普通函数,普通成员函数可以修改属性,而常对象不允许修改成员属性
//
//}
//
//
//int main()
//{
//
//	system("pause");
//	return 0;
//}

/*******************5.1友元——全局函数做友元******************************/
//友元目的:让一个函数或者类访问另一个类中的私有成员
//友元关键字:friend

//#include<iostream>
//using namespace std;
//#include<string>
//
建筑物类
//class building
//{
//	//goodgay全局函数是building好朋友,可以访问building中私有成员
//	friend void goodgay(building* building);
//public:
//	building()//构造函数赋初值
//	{
//		m_settingroom = "客厅";
//		m_badroom = "卧室";
//	}
//	string m_settingroom;//客厅
//private:
//	string m_badroom;//卧室
//};
//
全局函数
//void goodgay(building* building)
//{
//	cout << "好基友的全局函数正在访问:" << building->m_settingroom << endl;
//	cout << "好基友的全局函数正在访问:" << building->m_badroom << endl;
//}
//
//void test01()
//{
//	building building;
//	goodgay(&building);
//}
//int main()
//{
//	test01();
//	system("pause");
//	return 0;
//}

/*******************5.2友元——类做友元******************************/
//#include<iostream>
//using namespace std;
//#include<string>
//
类做友元
//class building;
基友类
//class goodgay
//{
//public:
//	goodgay();//类外实现构造函数
//	void visit();//参观函数,访问building中的属性
//	building* buil;
//};
//
建筑类
//class building
//{
goodgay类是本类的好朋友,可以访问本类中的私有成员
//	friend class goodgay;//(类作为友元)
//public:
//	building();//类外实现构函数
//	string m_settingroom;//客厅
//private:
//    string m_badroom;//卧室
//};
//
类外写成员函数
//goodgay::goodgay()
//{
创建一个建筑物的对象
//	buil = new building;//在堆区创建一个对象
//}
//
//void goodgay::visit()
//{
//	cout << "好基友正在访问:" << buil->m_settingroom <<endl;
//	
//	cout << "好基友正在访问:" << buil->m_badroom << endl;
//}
//
//building::building()
//{
//	m_settingroom = "客厅";
//	m_badroom = "卧室";
//}
//
//void test01()
//{
//	goodgay gg;
//	gg.visit();
//}
//
//int main()
//{
//	test01();
//	system("pause");
//	return 0;
//}

/*******************5.3友元——成员函数做友元******************************/
#include<iostream>
using namespace std;
#include<string>

class building;
class goodgay
{
public:
	goodgay();//类外实现成员构造函数
	void visit();//让visit函数可以访问building中的私有成员
	void visit2();//让visit函数不可以访问building中的私有成员
	building* buil;
};

//建筑类
class building
{
	//告诉编译器,goodgay类下的visit成员函数可以作为本类的好朋友,访问私有成员
	friend void goodgay::visit();
public:
	building();//类外实现成员构造函数
	string m_settingroom;//客厅
private:
    string m_badroom;//卧室
};

//类外定义成员构造函数
goodgay::goodgay()
{
	//在堆区创建一个building的对象
	buil=new building;
}

void goodgay::visit()
{
	cout << "visit函数正在访问:" << buil->m_settingroom << endl;
	cout << "visit函数正在访问:" << buil->m_badroom << endl;
}
void goodgay::visit2()
{
	cout << "visit2函数正在访问:" << buil->m_settingroom << endl;
	//cout << "visit2函数正在访问:" << buil->m_badroom << endl;
}


building::building()
{
	m_settingroom = "客厅";
	m_badroom = "卧室";
}

void test01()
{
	goodgay gg;
	gg.visit();
	gg.visit2();
}

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

4、运算符重载

/*****************1.加号运算符重载*****************************************/
//#include<iostream>
//using namespace std;
加号运算符重载
//class person
//{
//public:
//	//1.成员函数重载+号
//	/*person operator+(person& p)
//	{
//		person temp;
//		temp.m_A = this->m_A + p.m_A;
//		temp.m_B = this->m_B + p.m_B;
//		return temp;
//	}*/
//	int m_A;
//	int m_B;
//};
//
2.全局函数重载
person operator+(person& p1, person& p2)
{
	person temp;
	temp.m_A = p1.m_A + p2.m_A;
	temp.m_B = p1.m_B + p2.m_B;
	return temp;
}
//
函数重载的版本
//person operator+(person& p1, int num)
//{
//	person temp;
//	temp.m_A = p1.m_A +num;
//	temp.m_B = p1.m_B +num;
//	return temp;
//}
//void test01()
//{
//	person p1;
//	p1.m_A = 10;
//	p1.m_B = 10;
//	person p2;
//	p2.m_A = 20;
//	p2.m_B = 20;
//
//	//成员函数重载本质调用
//	//person p3 = p1.operator+(p2);
//
//	//全局函数重载本质调用
//	//person p3 = operator+(p1, p2);
//
//	//person p3 = p1 + p2;//(简化形式)
//	//cout << "p3.m_A=" << p3.m_A << endl;
//	//cout << "p3.m_B=" << p3.m_B << endl;
//	
//	//运算符重载,也可以发生函数重载
//	person p4 = p1 + 10;//(person+int)
//	cout << "p4.m_A=" << p4.m_A << endl;
//	cout << "p4.m_B=" << p4.m_B << endl;	
//}
//int main()
//{
//	test01();
//	system("pause");
//	return 0;
//}


/*****************2.左移运算符重载*****************************************/
//#include<iostream>
//using namespace std;
//
左移运算符重载
//class person
//{
//public:
//	friend ostream& operator<<(ostream& cout, person& p);
//	person(int a,int b)
//	{
//		m_A=a;
//		m_B=b;
//	}
//private:
//
//	//利用成员函数重载左移运算符 p.operator<<(cout) 简化版本p<<cout
//	//不会利用成员函数重载<<运算符,因为无法实现cout在左侧
//	//void operator<<()
//	//{}
//	int m_A;
//	int m_B;
//};
//
//     //只能利用全局函数重载左移运算符
//ostream & operator<<(ostream & cout, person& p)//本质operator<<(cout,p)简化为cout<<p  
//{
//	cout << "m_A=" << p.m_A << "m_B=" << p.m_B;
//	return cout;
//}
//
//void test01()
//{
//	person p(10,10);
//	cout << p <<"hello world" << endl;
//}
//int main()
//{
//	test01();
//	system("pause");
//	return 0;
//}

/*****************3.递增运算符重载*****************************************/
//前置递增返回的是引用,后置递增返回的是值
//#include<iostream>
//using namespace std;
//
递增运算符重载
//void func()
//{
//int a = 10;
//cout << ++a << endl;//11(前先算再赋值)
//cout << a << endl;//11
//
//int b = 10;
//cout << b++ << endl;//10(后先赋值再算)
//cout << b << endl;;//11
//}
//
//class myinteger
//{
//public:
//	friend ostream& operator<<(ostream& cout, myinteger myint);
//	myinteger()
//	{
//		m_num = 0;
//	}
//	//重载前置++运算符,返回引用是为了一直对一个数据进行递增操作
//	//前置递增返回的是一个引用
//	myinteger & operator++()
//	{
//		//先进行++运算
//		m_num++;
//		//再将自身返回
//		return *this;
//	}
//	//重载后置++运算符(后置递增返回的是值)
//	myinteger operator++(int)//括号加int为后置运算符重载
//	{
//		//先记录当时的结果
//		myinteger temp = *this;//*this代表自身
//		//后递增
//		m_num++;
//		//最后返回结果
//		return temp;
//	}
//private:
//	int m_num;
//};
//
重载<<运算符
//ostream& operator<<(ostream& cout, myinteger myint)
//{
//	cout << myint.m_num;
//	return cout;
//}
//
//void test01()
//{
//	myinteger myint;
//	cout << myint << endl;//0
//	cout << ++myint << endl;//1
//	cout << myint++ << endl;//1
//	cout << myint << endl;//2
//}
//int main()
//{
//	//func();
//	test01();
//	system("pause");
//	return 0;
//}

/*****************4.赋值运算符重载*****************************************/
//#include<iostream>
//using namespace std;
//
c++编译器至少给一个类添加4个函数
1.默认构造函数(无参,函数体为空)
2.默认析构函数(无参,函数体为空)
3.默认拷贝函数,对属性进行值拷贝(堆区空间重复释放)
4.赋值运算符 operator=对属性进行值拷贝(解决浅拷贝问题)
//
//class person
//{
//public:
//	person(int age)
//	{
//		m_age = new int(age);//在堆区开辟空间,手动开辟,手动释放
//	} 
//	~person()
//	{
//		if (m_age != NULL)
//		{
//			delete m_age;
//			m_age = NULL;
//		}
//	}
//
//	//重载赋值运算符,解决浅拷贝问题
//	person& operator=(person &p)
//	{
//	//编译器提供浅拷贝
//	//m_age=p.m_age;
//	//应该判断是否有属性在堆区,如果有先释放干净,再深拷贝
//		if (m_age != NULL)
//		{
//			delete m_age;
//			m_age = NULL;
//		}
//		//深拷贝
//		m_age = new int(*p.m_age);//堆区重新开辟一片空间
//	//返回对象本身,可以实现连续操作
//		return *this;
//	}
//	int *m_age;
//
//};
//
//void test01()
//{
//	person p1(18);
//	person p2(20);
//	person p3(30);
//	p3 = p2 = p1;//赋值:将p1的值赋给p2
//	//浅拷贝——简单的值拷贝和地址拷贝,导致堆区的内存重复释放,程序奔溃
//	//解决方案:利用深拷贝解决堆区数据重复释放问题
//	//深拷贝:开辟一块新内存,将数据复制到新内存中
//	cout << "p1的年龄为:" << *p1.m_age << endl;
//	cout << "p2的年龄为:" << *p2.m_age << endl;
//	cout << "p3的年龄为:" << *p3.m_age << endl;
//
//}
//int main()
//{
//	test01();
//	//int a = 10;
//	//int b = 20;
//	//int c = 30;
//	//c = b = a;
//	//cout << "a=" << a << endl;
//	//cout << "b=" << b << endl;
//	//cout << "c=" << c << endl;
//	system("pause");
//	return 0;
//}

/*****************5.关系运算符重载*****************************************/
//重载关系运算符,让两个自定义的类型对象进行对此操作
//#include<iostream>
//using namespace std;
//
//class person
//{
//public:
//	person(string name, int age)
//	{
//		m_name = name;
//		m_age = age;
//	}
//	//重载==号
//	bool operator==(person &p)
//	{
//		if (this->m_name == p.m_name && this->m_age == p.m_age)
//			return true;
//		else
//			return false;
//	}
//	//重载!=号
//	bool operator!=(person& p)
//	{
//		if (this->m_name == p.m_name || this->m_age == p.m_age)
//			return false;
//		else
//			return true;
//	}
//
//private:
//	string m_name;
//	int m_age;
//
//};
//
//void test01()
//{
//	person p1("李明", 18);
//	person p2("李明", 18);
//	if (p1 == p2)
//	{
//		cout << "p1相等于p2" << endl;
//	}	
//	else
//	{
//		cout << "p1与p2不相等" << endl;
//	}
//	if (p1 != p2)
//	{
//		cout << "p1不等于p2" << endl;
//	}
//	else
//	{
//		cout << "p1与p2相等" << endl;
//	}
//}
//int main()
//{
//	test01();
//	system("pause");
//	return 0;
//}


/*****************6.函数调用运算符重载*****************************************/
//函数调用运算符()也可以重载
#include<iostream>
#include<string>
using namespace std;

 //函数调用运算符重载;
 //打印输出类
class myprint
{
public:

	//重载的函数调用运算符
	void operator()(string test)//重载小括号
	{
		cout << test << endl;
	}
};

//加法类
class myadd
{
public:
	int operator()(int num1, int num2)
	{
		return num1 + num2;
	}
};
void test02()
{
	myadd MD;
	int ret=MD(2, 3);//仿函数
	cout << "ret=" << ret << endl;
	
	//创建匿名函数对象 类型+()
	//特点:当前行被执行完空间被释放
	cout << myadd()(10, 10) << endl;
}

void Myprint(string test)//正常打印函数
{
	cout << test << endl;
}

void test01()
{
	myprint MP;
	MP("hello world!");//重载函数的调用运算符调用
	//重载后的使用方式非常像函数的调用,因此称为仿函数
	//仿函数没有固定的写法,非常灵活
	Myprint("hello world");//正常打印函数调用函数
}

int main()
{
	test01();
	test02();
	system("pause");
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值