类和对象-对象特性

Content:

  1. 构造函数和析构函数
  2. 构造函数的分类和调用
  3. 拷贝构造函数调用时机
  4. 构造函数调用规则
  5. 深拷贝和浅拷贝
  6. 初始化列表
  7. 类对象作为类成员
  8. 静态成员函数
  9. 成员变量和成员函数分开存储
  10. this用法
  11. 空指针访问成员变量
  12. const修饰成员变量
  13. 友元-全局变量做友元
  14. 普通函数做友元
  15. 友元成员变量
  16. 类做友元

1、构造函数和析构函数

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

//构造函数和析构函数:完成对象初始化和清理工作,我们如果不提供构造和析构,编译器也会提供的,但是提供的是空实现

//构造函数:主要是创建对象时为对象的成员属性赋值,构造函数由编译器自动调用,无需手动调用

//析构函数:主要用于对象销毁前系统自动调用,执行一些清理工作 
 
class Person
{
public:
	//构造函数
	//1、无返回值也不用void
	//2、函数名称和类名相同
	//3、可以有参数,可以发生重载
	//4、程序在调用对象时会自动调用构造,无需手动调用,只调用一次
	
	Person()
	{
		cout<<"Person的构造函数"<<endl;
	 } 
	 
	 //析构函数
	 //1、无返回值,和void
	 //2、函数名和类名一样,在名称前加上符号~
	 //3、不可以有参数,不能重载
	 //4、 程序在对象销毁时会自动调用析构,无需手动调用,只调用一次
	 
	 ~Person()
	 {
	 	cout<<"Person的析构函数"<<endl; 
	  } 
	
 } ;
 
 
 //测试
 void test01()
 {
 	Person p;//栈区数据,执行完后就会释放 
 	
  } 
 

int main()
{
	//test01();
	Person p; //这步执行后继续往下走,遇到pause就停止,输入任意键后才会执行销毁操作 
	system("pause");
	return 0;
 } 

2、构造函数的分类和调用

#include<iostream>
using namespace std;

//构造函数的分类和调用 
//1、有参构造
//2、无参构造
//3、拷贝构造 

class Person
{
public:
	Person()
	//构造函数
	{
		cout<<"Person构造函数"<<endl;
	 } 
	
	Person(int a)
	{
		age = a;
		cout<<"Person有参构造函数"<<endl;
	 } 
	 
	 //拷贝构造函数
	 Person(const Person &p)
	 {
	 	//拷贝相同信息到这里来
		 cout<<"Person 拷贝构造函数调用"<<endl; 
		 age = p.age; 
		 
	 }
	 
	 //析构函数
	 ~Person()
	 {
	 	cout<<"Person的析构函数"<<endl;
	  } 
	  
	  
	  int age;
	  
 } ;


//调用
 void test()
 {
 	//1、括号法 
 	Person p;        //默认 
 	Person p1(10);   //有参构造 
 	Person p2(p1);   //拷贝构造
	 
	cout <<"p1的年龄为:"<<p1.age<<endl;
	cout <<"p2的年龄为:"<<p2.age<<endl; 
 	//注意事项:调用默认构造时不要加() 
 	//Person p3();//编译器认为i是函数声明 ,不会认为在创建对象 
 	
 	
 	//2、显示法
	Person p4;
	Person p5 = Person(20); //有参构造 
	Person p6 = Person(p5); //拷贝构造 
	//注意事项1:
	Person(10);//匿名对象  特点:当前行执行后,会立即收回匿名对象
	cout<<"aaaaa"<<endl; 
	
	//注意事项2:
	// 不要用拷贝构造函数 初始化匿名对象 
	//Person(p6); //重定义 
	 
	//3、隐式转换法 
	Person p7 = 30;//相当于写了Person p7 = Person(30)  有参构造
	Person p8 = p7;//拷贝 
	
	
 }

int main()
{
	//测试 
	test();
	
	
	system("pause");
	return 0;
 } 

3、拷贝构造函数调用时机

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

//拷贝构造函数调用时机

class Person
{
public:
	Person()
	{
		cout<<"Person默认的构造函数"<<endl;
	}
	
	Person(int age)
	{
		Age = age;
	}
	
	//拷贝构造
	Person(const Person &p)
	{
		
		cout<<"Person的拷贝构造"<<endl;
	 } 
	
	~Person()
	{
		cout<<"Person的析构函数"<<endl;
	}
	
	int Age;
 } ;

//拷贝构造函数调用的三种情况
//1、使用一个创建完毕的对象初始化一个新对象
void test01()
{
	Person p1;
	p1.Age = 10;
	Person p2(p1);
	
	cout<<"P2的年龄:"<<p2.Age <<endl;
 } 

//2、值传递的方式给函数传值
void doWork(Person p)
{
	
}

void test02()
{
	Person p;
	doWork(p);
}


//3、以值方式返回局部对象 
Person doWork2()
{
	Person p1;
	cout<<(int*)&p1<<endl;
	return p1;
}

void test03()
{
	Person p = doWork2();
	cout<<(int*)&p<<endl;
}

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

test01()结果:

test02()结果:

test03()结果:

4、构造函数调用规则

#include<iostream>
using namespace std;

//构造函数调用规则
//默认情况下,编译器会给一个类添加3个函数
//1、默认构造函数(无参、函数体为空)
//2、默认析构函数(无参、函数体为空)
//3、默认拷贝构造函数,对属性进行值拷贝

//调用函数规则如下:
//如果用户定义有参构造函数,C++不提供默认无参构造,但会提供默认拷贝构造
//用户定义拷贝构造函数,c++不会提供其他构造函数 

//如果写了有参构造函数,编译器就不不会再提供默认构造函数 ,但是依然会提供拷贝构造 

class Person
{
public:
	Person()
	{
		cout<<"默认构造函数"<<endl;
	}
	
	//有参
	Person(int age)
	{
		Age = age;
		cout<<"有参构造函数"<<endl;
	 } 
	
	~Person()
	{
		cout<<"默认析构函数"<<endl;
	}
	
	//拷贝构造函数
	Person(const Person &p)
	{
		Age = p.Age;
		cout<<"拷贝构造函数"<<endl;
	 } 
	 
	
	int Age;
	
 } ; 
 
 
void test()
{
	Person p;
	p.Age = 18;
	
	Person p2(p);
	cout<<"p2的年龄:"<<p2.Age<<endl;
}

void test01()
{
	Person p(20);
	
	Person p2(p);
}

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

5、深拷贝与浅拷贝

#include<iostream>
using namespace std;

//深拷贝和浅拷贝
//1、深拷贝:在堆区重新申请空间,进行拷贝操作 
//2、浅拷贝: 简单的赋值拷贝操作 


//浅拷贝带来问题是堆区内存重复释放 
//浅拷贝的问题用深拷贝进行解决 

//堆区的数据是先进后出操作,浅拷贝就会引起堆区重复操作的问题,很容易出问题 
class Person
{
public:
	Person()
	{
		cout<<"默认构造函数"<<endl;
	}
	
	Person(int age,int height)
	{
		Age = age;
		Height = new int(height);
		cout<<"有参构造函数"<<endl; 
	}
	
	~Person()
	{
		//析构代码,将堆区开辟数据做释放操作
		if(Height != NULL)
		{
			delete Height;
			Height = NULL;
		 } 
		cout<<"析构函数"<<endl;
	}
	
	Person(const Person &p)
	{
		cout<<"Person拷贝构造函数调用"<<endl;
		Age = p.Age;
		//Height = p.Height; 编译器默认实现的就是这行代码
		//深拷贝操作
		
		Height = new int(*p.Height);//解引用 
	}
	
	int Age;
	int *Height;
	
 } ;

void test()
{
	Person p1(18,160);
	cout<<"p1的年龄:"<<p1.Age<<p1.Height<<endl;
	
	Person p2(p1);
	cout<<"p2的年龄:"<<p2.Age<<p2.Height<<endl;
}



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

6、初始化列表

#include<iostream>
using namespace std;

//初始化列表
//c++  提供初始化列表用来初始化属性 
class Person
{
public:
	//传统初始化方法
//	Person(int a,int b,int c)
//	{
//		m_A = a;
//		m_B = b;
//		m_C = c;
//	 } 
	void Print()
	{
		cout<<"m_A:"<<m_A<<endl;
		cout<<"m_B:"<<m_B<<endl;
		cout<<"m_C:"<<m_C<<endl;
	 } 
	
	
	//初始化列表方法
	Person(int a,int b,int c):m_A(a),m_B(b),m_C(c)
	{
		
	}
	
	
private:
	int m_A;
	int m_B;
	int m_C;
		
};

int main()
{
	Person p1(1,2,3);
	p1.Print();
	
	system("pause");
	return 0;
}

7、类对象作为类成员

#include<iostream>
using namespace std;
//C++类中的成员可以是另一个类的对象,我们称该成员为对象成员 
class Phone
{
public:
	//构造 
	Phone(string name)
	{
		m_PhoneName = name;
		cout<<"Phone构造"<<endl;
	}	
	
	//析构 
	~Phone()
	{
		cout<<"Phone析构"<<endl; 
	}
	
	//成员属性 
	string m_PhoneName;
 }; 

class Person
{
public:
	//初始化列表可以告诉编译器用哪一个构造函数
	Person(string name,string pName):m_Name(name),m_Phone(pName)
	{
		cout<<"Person构造"<<endl;
	 } 
	 
	 //析构 
	 ~Person()
	 {
	 	cout<<"Person析构"<<endl;
	 }
	 
	 //成员函数 
	 void playGame()
	 {
	 	cout<<m_Name<<"使用"<<m_Phone.m_PhoneName<<"牌手机!"<<endl;
	 }
	 
	 //成员属性 
	 string m_Name;
	 
	 //phone类 
	 Phone m_Phone;
}; 

void test()
{
	//当类中成员是其他对象时,我们称该成员为 对象成员
	//构造顺序是:先调用对象成员的构造,在调用本类构造
	//析构顺序与构造相反
	Person p("张三","Huawei pro") ;
	p.playGame();
}

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

结果:

8、静态成员函数

#include<iostream>
using namespace std;

//静态成员就是在成员变量和成员函数前面加上关键字static,称为静态成员

//静态成员:
//1、静态成员变量:所有对象共享一份数据
//2、在编译阶段分配内存
//3、类内声明,类外初始化

//静态成员函数
//1、所有对象共享同一个函数
//2、静态成员函数只能访问静态成员变量 

class Person
{
public: 
	//静态成员函数 
	static void func()
	{
		age = 10;//静态成员函数可以访问静态成员变量 
		num = 11;//静态成员函数,不可以访问非静态成员变量  
		cout<<"func()"<<endl; 
	}
	
	//成员变量 
	static int age;//静态成员变量 
	static int num;//非静态成员变量 
	
	//静态成员函数也是有访问权限的 
private:
	static void func2()
	{
		
		cout<<"func2()"<<endl;
	 } 
};

//类内声明,类外要初始化 
int Person::age = 0; 
int Person::num = 0;

void test()
{
	//1、通过对象访问
	Person p;
	p.func();
	
	//2、通过类名访问 
	Person::func();
	
	//私有成员函数访问
	//p.func2(); //访问失败,类外访问不到私有的静态成员函数 
 } 
 
int main()
{
	test();
	system("pause");
	return 0;
}

9、成员变量和成员函数分开存储

#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 test()
 {
 	Person p;
 	//空对象占用空间的大小:1 
 	//编译器会给空对象也分配一个字节空间,是为了区分空对象占内存的位置
	 //每个空对象也应该有一个独一无二的内存地址 
 	cout<<"size of p:"<<sizeof(p)<<endl;
 }
 
 void test2()
 {
 	Person p;
 	cout<<"size of p:"<<sizeof(p)<<endl;
  } 

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

10、this用法

#include<iostream>
using namespace std;

class Person
{
public:
	Person(int age)
	{
		//this 指针指向被调用的成员函数所属的对象 
		this->age = age;
	}
	
	Person& addAge(Person p)
	{
		this->age += p.age;
		//返回对象本身,this指向p3的指针,而*this指向的是p3的这个对象本体 
		return *this ;
	}
	
	int age;	
};

//1、解决名称冲突 
void test()
{
	Person p2(18);
	cout<<"p2的年龄:"<<p2.age<<endl;
}

//2、返回对象本身用*this 
void test1()
{
	Person p1(10);
	Person p3(30);
	p3.addAge(p1).addAge(p1).addAge(p1);//60
	cout<<"p3的年龄:"<<p3.age<<endl; 
}

int main()
{
	//test();
	test1();
	system("pause");
	return 0;
}

11、空指针访问成员变量

#include<iostream>
using namespace std;

//空指针也可以调用成员函数,但是也要注意有没有用到this指针
//如果用到this指针,需要加以判断保证代码的健壮性 
class Person
{
public:
	void showAge()
	{
		cout<<"this is Age"<<endl;
	}
	
	void showPerson()
	{
		
		//报错原因是因为传入的指针是NULL ,添加一个判断,防止出现错误,即使是NULL,也会直接跳过! 
		if (this == NULL)
		{
			return;
		}
		cout<<"Age= "<<this->m_Age<<endl;
	}
	
	int m_Age;
};

void test()
{
	//创建一个空指针 
	Person *p1 = NULL;
//	p1->m_Age=11; 
	
	//指针调用,忘记的话,记得复习 
	p1->showAge();
	p1->showPerson();
}

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

12、const修饰成员变量

#include<iostream>
using namespace std;

//const修饰成员变量 

//1、常函数
//加const后称常函数
//常函数内不可以修改成员属性 
//成员属性声明时加关键字mutable,在常函数中依然可以修改

//2、常对象
//声明对象前加const称该对象为常对象
//常对象只能调用常函数 

class Person
{
public:
	void showPerson() const
	{
		//加const之后,就会只读的提示错误,这是一个常函数,只允许读操作 
		//m_Age = 10;
		m_age = 20;
		cout<<"this is Person"<<endl;
		//cout<<"m_Age= "<<m_Age<<endl;
		cout<<"m_age= "<<m_age<<endl;
	 } 
	
	int m_Age;	
	mutable int m_age;//特殊变量,在常函数中依然可以修改这个值,加关键字mutable 
};

void test()
{
	Person p1;
	Person p2;
	p2.showPerson();
	//p1.showPerson();
}

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

--------------------------------------------------------------------------------
#include<iostream>
using namespace std;

//1、const修饰成员变量 

class Man
{
public:
	//这里是错误的 
//	Man(int h):height(h) 
//	{
//		height = h;
//	}

	//可以使用初始化参数列表为成员变量赋值 
	Man(int h):height(h) 
	{
		
	}
	
private: 
	const int height;//只能读,不能修改 
	
};
int main()
{
	
	system("pause");
	return 0;
}
-------------------------------------------------------------------------------------
#include<iostream>
using namespace std;

//const修饰成员函数 

class Person
{
public:
	Person(int height,int weight);
	void display() const;//声明一个成员函数 

private:
	int m_height;
	int m_weight;	
	
};

Person::Person(int height,int weight)
{
	m_height = height;
	m_weight = weight;
}

//成员函数只能应用成员变量而不能修饰成员变量 
void Person::display() const
{
	//m_height = 120;不能修改了,只读格式 
	cout<<"height is:"<<m_height<<endl;
	cout<<"weight is:"<<m_weight<<endl;
}

int main()
{
	Person p1(175,160);//定义一个person对象 
	p1.display();
	
	system("pause");
	return 0;
}

13、友元-全局变量做友元

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

//想让类外特殊的一些函数或者类进行访问,就需要用到友元的技术
//友元就是让一个函数或者类访问另一个类中的私有成员

//关键字:friend 
class Building
{
	friend void goodBoy(Building *building);
public:
	Building()
	{
		this->m_settingroom = "客厅";
		this->m_beddingroom = "卧室"; 	
	}	

public:
	string m_settingroom;
private:
	string m_beddingroom;
};

void goodBoy(Building *building)
{
	cout<<"全局变量访问:"<<building->m_settingroom<<endl;
	cout<<"全局变量访问:"<<building->m_beddingroom<<endl;
 } 

void test()
{
	Building b;
	goodBoy(&b);
}

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

14、普通函数做友元

#include<iostream>
using namespace std;

class CShop
{
public:
	CShop(int size,int price);
	void showSize();
	void showPrice();
	friend int ChangePrice(CShop &shop,int price);//声明一个函数为友元 
private:
	int m_size;
	int m_price;
};

CShop::CShop(int size,int price)
{
	m_size = size;
	m_price = price;
}

void CShop::showSize()
{
	cout<<"size is :"<<m_size<<endl;
}

void CShop::showPrice()
{
	cout<<"Price is :"<<m_price<<endl;
}

//友元函数的定义 
int ChangePrice(CShop &shop,int price)
{
	shop.m_price = price;//友元函数中访问私有变量 
	return shop.m_price;
}

int main()
{
	//创建一个对象 
	CShop shop(100,2000);
	shop.showSize();
	shop.showPrice();
	
	//调用友元函数 
	ChangePrice(shop,3000);
	shop.showSize(); 
	shop.showPrice();
	 
	system("pause");
	return 0;
}

15、友元成员变量

#include<iostream>
using namespace std;

//友元不仅可以时一般的函数,还可以是类中的成员函数
 
class CShop;//提前声明表示稍后要定义的类 

class CCompany
{
public:
	void Display(CShop &shop);
 } ;


class CShop
{
public:
	CShop(int size,int price);
	friend void CCompany::Display(CShop &shop);	//CCompany中的成员函数友元 

private:
	int m_size;
	int m_price;//私有 变量 
};

void CCompany::Display(CShop &shop)
{
	cout<<"the price of shop is :"<<shop.m_price<<endl;
	cout<<"the size of shop is :"<<shop.m_size<<endl;
}

CShop::CShop(int size,int price)
{
	m_price = price;
	m_size = size;
}

int main()
{
	CShop shop(200,500);
	//shop.Display();
	
	CCompany company;//调用友元 
	company.Display(shop);
	
	system("pause");
	return 0;
}

16、类做友元

//将整个类都声明为友元
#include<iostream>
using namespace std;

class CShop;//提前声明表示稍后要定义的类 

class CCompany
{
public:
	void Display(CShop &shop);
 } ;


class CShop
{
public:
	CShop(int size,int price);
	friend CCompany; 

private:
	int m_size;
	int m_price;//私有 变量 
};

void CCompany::Display(CShop &shop)
{
	cout<<"the price of shop is :"<<shop.m_price<<endl;
	cout<<"the size of shop is :"<<shop.m_size<<endl;
}

CShop::CShop(int size,int price)
{
	m_price = price;
	m_size = size;
}

int main()
{
	CShop shop(200,500);//定义一个shop类初始化 
	//shop.Display();
	
	CCompany company;//调用友元 
	company.Display(shop);
	
	system("pause");
	return 0;
} 

类和对象结束!!!好累,这节真的很难理解,尽量还是结合书配套学,细节的东西太多了,还是得多敲代码,找问题的!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林语微光

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值