C++第二部分核心编程2(类和对象(封装,对象特性))

类和对象

1.封装

1.1 封装

#include<iostream>
using namespace std;
#include<string>
//class 类名{访问权限:属性/行为}
//圆的周长公式:s=2*π*r。

const double pi = 3.14;
//class代表设计一个类,类后面紧跟着的就是类名称
//类中的属性和行为都称为“成员”
//属性   成员属性,成员变量
//行为   成员函数,成员方法
class circle//圆类
{
	//访问权限
public:
	//属性,一般都是一些变量
	int m_r;//半径

	//行为,一般都是函数
	//获取圆的周长
	double calculatezc()
	{
		return 2 * pi*m_r;
	}
};

int main()
{
	//通过圆类 创建具体的圆;
	//实例化(通过一个类 创建一个对象的过程)
	circle c1;//对象
	//给圆对象 的属性进行赋值
	c1.m_r = 10;

	cout << "圆的周长为:" << c1.calculatezc() << endl;




	system("pause");
	return 0;
}

1.2 设计学生类

设计一个学生类,属性有姓名和学号,可以给姓名和学号赋值,可以显示学生的姓名和学号。

class student
{
	//访问权限-公共权限
public:
	//属性,一般是变量
	string m_name;
	int m_id;
	//行为
	void showstudent()
	{
		cout << "姓名:" << m_name << "  学号" << m_id << endl;
	}

	//也可以给姓名赋值
	void setname(string name)
	{
		m_name = name;
	}

	void setid(int  id)
	{
		m_id = id;
	}

};
int main()
{
	//实例化对象
	student s1;
	//给属性赋值
	//s1.m_name = "胖子";
	s1.setname("胖子");
	//s1.m_id = 1;
	s1.setid(1);
	//显示学生信息
	s1.showstudent();
	/*student s2;
	s2.m_name = "嫖客";
	s2.m_id = 2;
	s2.showstudent();*/
	


	system("pause");
	return 0;
}

1.3三种保护权限

public 公共权限 : 成员类内可以访问,类外可以访问。
protected 保护权限 : 成员类内可以访问,类外不可以访问儿子可以访问父亲的保护内容。
private 私有权限 : 成员类内可以访问,类外不可以访问儿子不可以访问父亲的私有内容。


//public 公共权限              成员类内可以访问,类外可以访问
//protected 保护权限           成员类内可以访问,类外不可以访问 儿子可以访问父亲的保护内容
//private 私有权限             成员类内可以访问,类外不可以访问 儿子不可以访问父亲的私有内容

class person
{
	//公告权限
public:
	string m_name;//姓名
protected:
	string m_car;//汽车
private:
	int m_password;//银行卡密码
public:
	void func()
	{
		m_name = "张三";
		m_car = "拖拉机";
		m_password = 123456;
	}
};

int main()
{
	person p1;
	p1.m_name = "李四";
	//p1.m_car = "奔驰"   //类外访问不了
	


	system("pause");
	return 0;
}

1.4 struct和class的区别

struct和class唯一的区别在于默认的访问权限的不同.
struct默认为共有。
class默认为私有。

class c1
{
	int m_a;
	
};
struct c2
{
	int m_a;
};
int main()
{
	
	c1 c1;
	//c1.m_a = 100;//报错,class默认私有
	c2 c2;
	c2.m_a = 100;



	system("pause");
	return 0;
}

1.5 成员属性设为私有

可以自己控制读写权限。
对于写可以检测数据的有效性。

class person
{

public:
	//设置姓名
	void setname(string name)
	{
		m_name = name;
	}

	//获取姓名
	string getname()
	{
		return m_name;
	}
	//获取年龄
	int getage()
	{
		m_age = 0;
		return m_age;
	}
	//设置年龄
	void setage(int age)
	{
		if (age < 150 && age>0)
		{
			m_age = age;
		}
		else 
		{
			m_age = 0;
			cout << "你这个老妖" << endl;
			return;
		}
	}

	void setlover(string lover)
	{

		m_lover = lover;
	}

private:
	//姓名  可读可写
	string  m_name;
	//年龄 只读
	int m_age;
	//情人 只写
	string m_lover;

};


int main()
{

	person p;
	p.setname("张三");
	
	cout << "姓名为:" << p.getname() << endl;
	p.setage(1000);
	cout << "年龄为:" << p.getage() << endl;
	//p.setlover = "胖子";//数据无法访问,只写
	//cout << "情人为:" << p.getlover() << endl;

	system("pause");
	return 0;
}

1.6 练习案例1

设计立方体类。
求出立方体的面积和体积。
分别用全局函数和成员函数判断两个立方体是否相等。


class cube
{
	//访问权限
public:
	//属性
	int m_l;
	int m_w;
	int m_h;

	void  set_l(int l)
	{
		m_l = l;
	}
	int get_l()
	{
		return m_l;
	}


	void  set_w(int w)
	{
		m_w = w;
	}
	int get_w()
	{
		return m_w;
	}

	void  set_h(int h)
	{
		m_h = h;
	}
	int get_h()
	{
		return m_w;
	}
	//行为
	int cube_volume()
	{
		return m_l*m_w*m_h;
	}
	int cube_surface_area()
	{
		return 2 * (m_l*m_w + m_l*m_h + m_w*m_h);
	}

	void issame(cube &c)//用局部函数进行判断时,只要传一个参数就行了,本身自带一个,然后传入一个,就可以进行对比了
	{
		if (cube_surface_area() == c.cube_surface_area() && cube_volume() == c.cube_volume())
		{
			cout << "这两个立方体相等" << endl;
		}
		else
		{
			cout << "这两个立方体不相等" << endl;
		}
	}


};
//全局函数
void issame(cube &c1,cube &c2)
{
	if (c1.cube_surface_area() == c2.cube_surface_area() && c1.cube_volume() == c2.cube_volume())
	{
		cout << "这两个立方体相等" << endl;
	}
	else
	{
		cout << "这两个立方体不相等" << endl;
	}
}

int main()
{
	cube c1;
	cout << "请输入第一个立方体的长 宽 高" << endl;
	cin >> c1.m_l;
	cin >> c1.m_w;
	cin >> c1.m_h;
	//c1.set_l(10);//这样也可以滴
	//c1.set_w(10);
	//c1.set_h(10);
	cout << "第一个立方体的表面积为" << c1.cube_surface_area()<<endl;
	cout << "第一个立方体的体积积为" << c1.cube_volume() << endl;
	cube c2;
	cout << "请输入第二个立方体的长 宽 高" << endl;
	cin >> c2.m_l;
	cin >> c2.m_w;
	cin >> c2.m_h;
	cout << "第二个立方体的表面积为" << c2.cube_surface_area() << endl;
	cout << "第二个立方体的体积积为" << c2.cube_volume() << endl;
	//issame(c1, c2);
	/*if (c1.cube_surface_area() == c2.cube_surface_area() && c1.cube_volume() == c2.cube_volume())//放到全局函数中
	{
		cout << "这两个立方体相等" << endl;
	}
	else
	{
		cout << "这两个立方体不相等" << endl;
	}*/

	c1.issame(c2);//  学会这个哦
	

	system("pause");
	return 0;
}

1.7 自己的案例练习2

设计一个圆形类,和一个点类,计算点和圆的关系。

class circle
{
	//访问权限
public:
	//属性
	int cx;   //圆心的横坐标
	int cy;   //圆心的纵坐标
	int cr;   //圆的半径
	void set_x(int x)
	{
		cx = x;
	}

	int get_x()
	{
		return cx;
	}
	void set_y(int y)
	{
		cy = y;
	}

	int get_y()
	{
		return cy;
	}
	void set_r(int r)
	{
		cr = r;
	}

	int get_r()
	{
		return cr;
	}
	//行为
};
class point
{
public:
	int px;   //点的横坐标
	int py;   //点的纵坐标
	void set_x(int x)
	{
		px = x;
	}

	int get_x()
	{
		return px;
	}
	void set_y(int y)
	{
		py = y;
	}

	int get_y()
	{
		return py;
	}
};

void relation(circle &c1,point &p1)
{
	if (sqrt((c1.get_x() - p1.get_x())*(c1.get_x() - p1.get_x()) + (c1.get_y() - p1.get_y())*(c1.get_y() - p1.get_y())) < c1.get_r())
	{
		cout << "点在圆的里面" << endl;
	}
	else if (sqrt((c1.get_x() - p1.get_x())*(c1.get_x() - p1.get_x()) + (c1.get_y() - p1.get_y())*(c1.get_y() - p1.get_y())) == c1.get_r())
	{
		cout << "点在圆上" << endl;
	}
	else
	{
		cout << "点在圆的外面" << endl;
	}

}
int main()
{
	circle c1;
	c1.set_x (0);
	c1.set_y(0);
	c1.set_r(1);
	point p1;
	p1.set_x(0);
	p1.set_y(1);
	relation(c1, p1);

	system("pause");
	return 0;

}

1.8 课程的的案例2做法

设计一个圆形类,和一个点类,计算点和圆的关系。

class point
{
private:
	int px;   //点的横坐标
	int py;   //点的纵坐标
public:
	void set_x(int x)
	{
		px = x;
	}

	int get_x()
	{
		return px;
	}
	void set_y(int y)
	{
		py = y;
	}

	int get_y()
	{
		return py;
	}
};
class circle
{
	//访问权限
private:
	//属性
	point m_center;//圆心
	int cr;   //圆的半径
public:

	void set_r(int r)
	{
		cr = r;
	}

	int get_r()
	{
		return cr;
	}
	void setcenter(point center)
	{
		m_center = center;
	}
	point getcenter()
	{
		return m_center;
	}
};
void isincircle(circle &c,point &p)
{
	//计算两点之间的距离的平方
	int distance = (c.getcenter().get_x() - p.get_x())*(c.getcenter().get_x() - p.get_x()) + (c.getcenter().get_y() - p.get_y())*(c.getcenter().get_y() - p.get_y());
		//计算半径的平方
	int rdistance = c.get_r()*c.get_r();
		if (distance < rdistance)
		{
		cout << "点在圆的里面" << endl;
		}
		else if (distance == rdistance)
		{
			cout << "点在圆上" << endl;
		}
		else
		{
			cout << "点在圆的外面" << endl;
		}
}

int main()
{
	//创建圆
	circle c1;
	c1.set_r(10);
	//创建点
	point center;
	center.set_x(0);
	center.set_y(0);
	c1.setcenter(center);
	point p1;
	p1.set_x(10);
	p1.set_y(0);
	isincircle(c1, p1);
	
	
	system("pause");
	return 0;

}

2.对象特性

2.1构造函数和析构函数


#include<iostream>
#include<string>
using namespace std;
//对象的初始化和清理
//1.构造函数 进行初始化操作
class person
{
public:
	//1.1 构造函数
	//没有返回值,也没有void
	//函数名 与类名相同
	//构造函数可以有参数,可以发送重载
	//创建对象的时候,构造函数会自动调用,有且只有一次

	person()
	{
		cout << "person构造函数的调用" << endl;
	}
	//析构函数 进行清理的操作
	//没有返回值 不写void
	//函数名和类名相同 在名称前面加~
	//析构函数不可以有参数,不可以重载
	//销毁对象前,析构函数会自动调用,有且只有一次
	~person()
	{
		cout << "person析构函数的调用" << endl;
	}


};
//构造和析构都是必须有的实现,如果我们不提供,编译器会提供一个空实现的构造和析构
void test01()
{
	person p;//在栈上的数据,test01执行完毕后,释放这个对象
}


int main()
{
	
	test01();//创建对象的时候,构造函数会自动调用,有且只有一次
	//or
	//person p;//看得到构建,因为析构会在你任意键结束后的一瞬间出现,看不怎么到。


	system("pause");
	return 0;

}

2.2 构造函数的分类和调用

//构造函数的分类和调用
//分类
class person
{
public:
	// 构造函数
	int age;

	person()//无参
	{
		cout << "person无参构造函数的调用" << endl;
	}
	
	person(int a)//有参构造
	{
		age = a;
		cout << "person有参构造函数的调用" << endl;
	}
	//拷贝构造
	person(const person &p)
	{
		age = p.age;
		cout << "person拷贝构造函数的调用" << endl;
	}

	//析构函数 

	~person()
	{
		cout << "person析构函数的调用" << endl;
	}


};

void test01()
{
	//1.括号法
	person p1;//默认无参构造函数的调用
	person p2(10);//有参构造函数的调用
	person p3(p2);//拷贝构造函数的调用
	
	//注意事项
	//调用默认构造函数时候,不要加()
	//person p1(),因为这行代码,编译器会认为是一个函数的声明,不会认为在创建对象
	cout << "p2的年龄为:" << p2.age << endl;
	cout << "p3的年龄为:" << p3.age << endl;
	//2.显示法
	person p1;
	person p2 = person(10);//有参构造, person(10)叫做匿名对象,特点:当前行执行结束后,系统会立即回收匿名对象
	person p3 = person(p2);//拷贝构造

	//注意事项2
	//不要利用拷贝构造函数初始化匿名对象,比如person(p3)

	//3.隐式转换法
	person p4 = 10;//相当于person p4=person p4=person(10);有参构造



}
int main()
{
	
	test01();

	system("pause");
	return 0;

}

2.3 拷贝构造函数的调用时机


class person
{
public:
	//构造函数
		person()
		{
			cout << "person默认无参构造函数的调用" << endl;
		}

		person(int age)
		{
			cout << "person有参构造函数的调用" << endl;
			m_age = age;
		}
		person(const person &p)
		{
			cout << "person拷贝构造函数的调用" << endl;
			m_age =p.m_age ;
		}

   //析构函数
		~person()
		{
			cout << "person析构函数的调用" << endl;
		}
		int m_age;
		
};
//1.使用一个已经创建完毕的对象来初始化一个新对象
void test01()
{
	person p1(20);
	person p2(p1);
	cout << "p2的年龄:" << p2.m_age << endl;

}
//2.值传递的方式给函数参数传值
void dowork(person p)
{

}
void test02()
{
	person p;
	
	dowork(p);

}
//3.以值方式返回局部对象
person dowork2()
{
	person p1;
	return p1;
}
void test03()
{
	
	person p = dowork2();
}
int main()
{
	//test01();
	//test02();
	  test03();

	system("pause");
	return 0;

}

2.4 构造函数调用规则

1.创建一个类,c++编译器会给每个类都添加至少3个函数:
默认构造(空实现),
析构函数(空实现),
拷贝构造(值拷贝)。
2.如果我们写了有参构造函数,编译器就不再提供默认构造,依然提供拷贝构造。
3.如果我们写了拷贝构造函数,编译器就不再提供其他构造函数。

class person
{
public:
	person()
	{
		cout << "person的默认无参构造函数" << endl;
	}
	person(int age)
	{
		m_age = age;
		cout << "person的有参构造函数" << endl;
	}
	person(const person &p)
	{
		m_age = p.m_age;
		cout << "person的拷贝构造函数" << endl;
	}

	~person()
	{
		cout << "person的析构函数" << endl;
	}
	int m_age;
};
void test01()
{
	person p1;
	p1.m_age = 18;

	person p2(p1);
	cout << "p2的年龄:" << p2.m_age << endl; 
}
void test02()
{
	person p(28);
	person p2(p);
	cout << "p2的年龄:" << p2.m_age<<endl;

}

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

}

2.5 深拷贝和浅拷贝

class person
{
public:
	        person()
			{
				cout << "person的默认无参构造函数" << endl;
			}
			person(int age, int height)
			{
				m_age = age;
				m_height = new int( height );
				cout << "person的有参构造函数" << endl;
			}
			//自己实现一个拷贝构造函数,解决浅拷贝带来的问题
			person(const person &p)
			{
				cout << "拷贝函数调用" << endl;
				m_age = p.m_age;
				//m_height = p.m_height;编译器默认实现的就是这行代码
				//深拷贝操作:
				m_height = new int(*p.m_height);

			}
			~person()
			{     //比如我在堆区开辟了一个内存,那个么析构函数的作用就出现了,将堆区开辟的数据释放
				if (m_height != NULL)
				{
					delete m_height;
					m_height = NULL;
				}
				cout << "person的析构函数" << endl;
			}
			int m_age;
			int *m_height;//身高
};
void test01()
{
	//浅拷贝带来的问题就是堆区的内存重复释放,利用深拷贝解决
	//在没有深拷贝前,下面这个代码会崩掉
	person p1(18,160);
	cout << "p1的年龄:" << p1.m_age<<"p1的身高:"<<*p1.m_height<<endl;
	person p2(p1);
	cout << "p2的年龄:" << p2.m_age << "p1的身高:" << *p2.m_height<< endl;
}

int main()
{
	test01();

	system("pause");
	return 0;
}

2.6初始化列表

感觉没啥用,哈哈哈哈哈哈哈哈哈哈!!!!!!!

class person
{
public:
	person() :m_age(20), m_height(160)
	{
		cout << "年龄:" <<m_age<< endl;
		cout<<"身高:"<< m_height << endl;
	}


	int m_age;
	int m_height;
};
void test01()
{
	person p;
}

int main()
{
	test01();
	

	system("pause");
	return 0;

}

2.7类对象作为类成员

class phone
{
public:
	phone(string pname)
	{
		cout << "phone的构造函数调用" << endl;
		m_pname = pname;
	}
	~phone()
	{
		cout << "phone的析构函数调用" << endl;
	}
	//手机品牌名称
	string m_pname;

};
class person
{
public:
	//phone m_phone =pname;隐式转换法
	person(string name, string pname):m_name(name), m_phone(pname)
	{
		cout << "person的构造函数调用" << endl;
	}
	~person()
	{
		cout << "person的析构函数调用" << endl;
	}
	string m_name;
	phone m_phone;
};
//当其他类的对象作为本类成员,构造时候先构造类对象,再构造自身
void test()
{
	person p("张三", "苹果手机");
	cout << p.m_name << "拿着" <<p.m_phone.m_pname << endl;
}

int main()
{

	test();
	system("pause");
	return 0;
}

2.8 静态成员-静态成员变量

class person
{
public:
	//1.所有对象都共享同一份数据
	//2.编译阶段就分配内存
	//3.类内声明,类外初始化操作
	static int m_a;
	//静态成员变量也是有访问权限的
private://类外访问不到私有的
	static int m_b;



};
int person:: m_a = 100;//第三点 类内声明,要类外初始化操作
int person::m_b = 200;
void test()
{
	person p;
	cout << p.m_a << endl;
	person p2;
	p2.m_a = 200;
	cout << p2.m_a << endl;
	cout << p.m_a << endl;//也变成200了。共享数据

}void test02()
{
	//静态成员变量 不属于某个对象上,所有对象都共享同一份数据
	//因此静态成员变量有两种访问方式

	//1.通过对象进行访问
	person p;
	cout << p.m_a << endl;

	//2.静态的还可以通过类名进行访问
	cout << person::m_a << endl;
}


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

2.9 静态成员-静态成员函数

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

class person
{
public:
	//静态成员函数
	static void func()
	{
		m_a = 100;//静态成员函数只能访问静态成员变量
		//m_b = 100;//报错,因为不是静态的,因为无法区分m_b到底是哪个对象的属性
		cout << "static void func调用" << endl;
	}
	static int m_a;//静态成员变量
	int m_b;
};
int person::m_a =0;
void test()
{
	//通过对象访问
	person p;
	p.func();
	//通过类名访问
	person::func();

}


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

2.10 成员变量和成员函数

分开存储.

class person
{
public:
	int m_a;//非静态成员变量,属于类对象上
	static int m_b;//静态成员变量,不属于类对象上
	void func()//非静态成员函数,不属于类对象
	{

	}
	static void func2()//静态成员函数,不属于类对象
	{}

};
int person::m_b = 10;
void test()
{
	person p;
	//空对象占用的内存空间:1
	//C++编译器会给每个空对象也分配一个字节空间,是为了区分空对象占内存的位置
	//每个空对象也应该有一个独一无二的内存地址
	cout << "sizeof p=" << sizeof(p) << endl;
}
void test02()
{
	person p;
	cout << "sizeof p=" << sizeof(p) << endl;
}

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

2.11 this指针

class person
{
public:
	person(int age)
	{//this指针指向的是被调用的成员函数的对象
		this->age = age;
	}
	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;
}
//返回对象本身用*this
void test02()
{
	person p1(10);
	cout << "p1的年龄:" << p1.age << endl;
	person p2(10);
	p2.personaddage(p1).personaddage(p1).personaddage(p1);
	cout << "p2的年龄:" << p2.age << endl;
	
}

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

2.12 空指针访问成员函数


class Person
{
public:
	void showClassName()
	{
		cout << "this is person class" << endl;
	}
	int m_age;
	void showPersonAge()
	{
		//报错原因:传入的指针为空
		//所以加入判断
		if (this == NULL)
		{
			return ;
		}
		cout << "age=" << this->m_age<<endl;
	}

};
void test01()
{
	Person *p = NULL;
	p->showClassName();
   // p->showPersonAge;//运行这个会报错,为什么呢,看上面的解释

}

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

2.13const修饰成员函数

//常函数

class person
{
public: 
	//this指针的本质 是指针常量 指针的指向是不可以修改的
	//const person*canst this;
	//在成员函数后面加const,修饰的是this指向,让指针指向的值也不可以修改
	void showperson()const
	{
		this->m_b = 100;

		//this->m_a = 100;
		//this->NULL;//this指针不可以修改指针的指向的
	}
	void func()
	{

		m_a = 100;
	}

	int m_a;
	mutable int m_b;//特殊变量,即使在常函数中,也可以修改这个值
};
void test()
{
	person p;
	p.showperson();

}
//常对象
void test02()
{
	const person p;//在对象前加上const,变为常对象
	//p.m_a = 100;//不可以改,会报错
	p.m_b = 100;//m_B是特殊值,在常对象下也可以修改
	//常对象只能调用常函数
	p.showperson();
	//p.func();//不允许,报错,因为常对象不允许调用普通成员函数,因为普通成员函数可以修改属性

}

int main()
{
	test();

	system("pause");
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值