2、封装(C++核心语法)

1 设计一个类,求圆的周长

1.1 class + 类名{成员函数 成员变量}

1.2 公共权限 public

1.3 设计成员属性

	1.3.1 半径 int m_R

1.4 设计成员函数

	1.4.1 获取圆周长	double calculateZC()
	1.4.2 获取圆半径	int getR()
	1.4.3 设置圆半径	void setR(int r)

1.5 通过类创建对象过程 称为实例化对象

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

//设计一个类,求圆的周长

const double PI = 3.14;

//class + 类名
//周长公式 :   2 * pi * m_R
class Circle
{
public: //公共权限

	//类中的函数  称为 成员函数  成员方法
	//求圆周长
	double calculateZC()
	{
		return 2 * PI * m_R;
	}

	//设置半径
	void setR(int r)
	{
		m_R = r;
	}

	//获取半径
	int getR()
	{
		return m_R;
	}


	//类中的变量   称为成员变量  成员属性
	//半径
	int m_R;

};

void test01()
{
	Circle  c1; //通过类 创建一个对象   实例化对象
	
	//给c1 半径赋值
	//c1.m_R = 10;
	c1.setR(10);


	//求c1圆周长
	cout << "圆的半径为: " << c1.getR() << endl;
	cout << "圆的周长为: " << c1.calculateZC() << endl;

}



//2 设计一个学生类,属性有姓名和学号,可以给姓名和学号赋值,可以显示学生的姓名和学号
class Student
{
public:


	//设置姓名
	void setName(string name)
	{
		m_Name = name;
	}

	//设置学号
	void setId(int id)
	{
		m_Id = id;
	}

	//显示学生信息
	void showStudent()
	{
		cout << "姓名:" << m_Name << " 学号: " << m_Id << endl;
	}

	//属性:
	//姓名
	string m_Name;
	//学号
	int  m_Id;
};

void test02()
{
	Student s1;
	s1.m_Name = "张三";
	s1.m_Id = 1;

	cout << "姓名:" << s1.m_Name << " 学号: " << s1.m_Id << endl;

	Student s2;
	s2.setName("李四");
	s2.setId(2);
	s2.showStudent();

	Student s3;
	s3.setName("王五");
	s3.setId(3);
	s3.showStudent();
}


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

	system("pause");
	return EXIT_SUCCESS;
}

2 内联函数

		宏缺陷1 : 必须要加括号保证运算完整
		宏缺陷2 : 即使加了括号,有些运算依然与预期不符
	普通函数不会出现缺陷
	
	以下情况可能不会将函数进行内联编译:
	不能存在任何形式的循环语句、不能存在过多的条件判断语句
	函数体不能过于庞大、不能对函数进行取址操作。

2.1 总结:内联函数只是给编译器一个建议,但是编译器不一定接受这个建议;
如果没有声明函数为内联函数,编译器可能会将此函数做内联函数。
一个好的编译器会将小的、简单的函数加上关键字inline 做内联函数。

内联函数具有普通函数的所有行为,唯一的不同是会在适当的地方像预定义一样展开,
不需要函数调用的开销。

//函数的声明和实现必须同时加关键字 inline 才算内联函数
//内联函数 好处 :解决宏缺陷,本身是一个函数,带来宏优势,以空间换时间,在适当的时候做展开

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

	//宏缺陷1 : 必须要加括号保证运算完整
	#define  MYADD(x,y)  ((x) +(y))
	void test01()
	{
		int a = 10;
		int b = 20;
		int ret = MYADD(a, b) * 20;
		cout << ret << endl;//600
	}

	//宏缺陷2:  即使加了括号,有些运算依然与预期不符

	#define MYCOMPARE(a,b)  (((a) < (b)) ? (a) : (b))

	//普通函数 不会出现与预期结果不符的问题
	void myCompare(int a, int b)
	{
		int ret = a < b ? a : b;
		cout << "ret = " << ret << endl;
	}

	void test02()
	{
		int a = 10;
		int b = 20;

		myCompare(++a, b);

		//int ret = MYCOMPARE(++a, b); //预期是 11 结果变为12   (((++a) < (b)) ? (++a) : (b))

		//cout << "ret = " << ret << endl;

	}


	//内联函数
	//函数的声明和实现必须同时加关键字 inline  才算内联函数
	//内联函数 好处  :解决宏缺陷,本身是一个函数,带来宏优势,以空间换时间,在适当的时候做展开
	inline void func();
	inline void func(){};
	//类内部的成员函数 在函数前都隐式加了关键字 inline


	int main(){

		//test01();
		test02();
		system("pause");
		return EXIT_SUCCESS;
	}

3 函数的默认参数和占位参数

默认参数:
	3.1.1 可以给函数的形参添加默认值
	3.1.2 默认参数 语法  形参  类型 变量  = 默认值
	3.1.3 int func(int a, int b = 10 , int c = 10)	
	3.1.4 注意事项 ,如果有一个位置有了默认参数,那么从这个位置起,从左到右都必须有默认值
	3.1.5 函数的声明和实现 只能有一个 提供默认参数,不可以同时加默认参数
占位参数:
	3.2.1 只写一个类型进行占位,调用时候必须要传入占位值
	3.2.2 void func2(int a , int = 1)
	3.2.3 占位参数也可以有默认值
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;


//默认参数 语法  形参  类型 变量  = 默认值
//注意事项 ,如果有一个位置有了默认参数,那么从这个位置起,从左到右都必须有默认值
int func(int a, int b = 10 , int c = 10)
{
	return  a + b + c;
}


void test01()
{
	cout << func(20 , 10) << endl;//20赋值给a 10赋值给b

}


//函数的声明和实现 只能有一个 提供默认参数,不可以同时加默认参数
void myFunc(int a = 10, int b = 10);
void myFunc(int a , int b){};



//占位参数  只写一个类型进行占位,调用时候必须要传入占位值
//占位参数  用途? 目前没用
void func2(int a , int = 1)
{

}

void test02()
{
	func2(10);
}

int main(){

	test01();

	system("pause");
	return EXIT_SUCCESS;
}

4 函数重载

	基本原理:编译器可能将不同参数的函数重新命名为不同名的函数,
	当传入不同的参数的时候,调用不同的函数。

4.1 函数重载条件

		4.1.1 在同一个作用域
		4.1.2 函数名称相同
		4.1.3 参数个数、类型、顺序不同(其一有差异即可)

4.2 函数的返回值不可以作为函数重载的条件

4.3 注意事项

		4.3.1 加const和不加const的引用可以作为重载条件
		4.3.2 函数重载碰到默认参数  注意避免二义性出现
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;

//函数重载条件
//1、在同一个作用域
//2、函数名称相同
//3、参数个数、类型、顺序不同

//class Person
//{
//public:
//	void func()   成员函数 而不是全局函数
//	{
//	}
//};

void func()
{
	cout << "func()调用" << endl;
}

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

void func(double a)
{
	cout << "func(double a)调用" << endl;
}

void func(int a, double b)
{
	cout << "func(int a ,double b)调用" << endl;
}

void func(double a, int b)
{
	cout << "func(double a, int b)调用" << endl;
}

//返回值可不可以作为函数重载的条件 答案:不可以
//int func(int a, double b)
//{
//	cout << "func(int a ,double b)调用" << endl;
//}



void test01()
{
	func(1,3.14);
}



//函数重载中 引用两个版本
//void myFunc(int a)
//{
//	cout << "myfunc(int a )调用" << endl;
//}
void myFunc(int &a) // int & a  = 10;
{
	cout << "myfunc(int &a )调用" << endl;
}
void myFunc(const int &a) // const int &a = 10;
{
	cout << "myfunc( const int &a )调用" << endl;
}


void test02()
{
	int a = 10;
	//myFunc(a);//需要避免二义性出现

}


//函数重载碰到默认参数  注意避免二义性出现
void func2(int a , int b = 10)
{

}

void func2(int a)
{

}

void test03()
{
	//func2(10); //出现二义性
}


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

	system("pause");
	return EXIT_SUCCESS;
}

5 extern C 浅析

5.1 用途:在C++中调用C语言文件

5.2 在C++中有函数重载,会对函数名称做修饰,

因此导致调用C语言的函数链接失败

5.3 利用extern C可以解决问题

	5.3.1 方法1
		在C++代码中加入extern "C" void show();
		//告诉编译器  show函数用C语言方式 做链接
	5.3.2 方法2
		在C语言的头文件中加入6行代码
		#ifdef __cplusplus  // 两个下划线  __  c plus plus
		extern "C" {
		#endif
		//这里放C语言头文件内容
		#ifdef __cplusplus
		}
		#endif

//main.cpp

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

//告诉编译器  show函数用C语言方式 做链接
//extern "C" void show();


void test01()
{
	show();//_Z4showv;在C++中有函数重载会修饰函数名,但是show是c语言文件,因此链接失败
}

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

//test.h

#ifdef __cplusplus  // 两个下划线  __  c plus plus
extern "C" {
#endif

#include <stdio.h>
	void show();

#ifdef __cplusplus
}
#endif

//test.c

#include "test.h"

void show()
{
	printf("hello world\n");
}

6 C和C++的封装

struct
C语言:不能包含函数
C++语言:可以包含函数

6.1 C语言的封装:

缺陷:将属性和行为分离

6.2 C++语言的封装

将属性和行为作为一个整体,来表现生活中的事物
将属性和行为 加以权限控制

6.3 访问权限:

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

//package.c

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

struct Person
{
	char  name[64];
	int age;
};

void PersonEat(struct Person * p)
{
	printf("%s在吃人饭\n",p->name);
}

void test01()
{
	struct Person p;
	strcpy(p.name, "张三");
	p.age = 10;

	PersonEat(&p);
}


struct Dog
{
	char name[64];
	int age;
};

void DogEat(struct Dog * dog)
{
	printf("%s在吃狗粮\n", dog->name);
}

void test02()
{
	struct Dog d;
	strcpy(d.name, "旺财");
	d.age = 100;

	DogEat(&d);


	struct Person p;
	strcpy(p.name, "老王");

	DogEat(&p);

}

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

	system("pause");
	return EXIT_SUCCESS;
}

//package.cpp

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

struct  Person
{
	//公共权限
public:
	char name[64];
	int age;

	void PersonEat()
	{
		printf("%s在吃人饭\n", name);
	}
};

struct Dog
{
	//公共权限
public:
	char name[64];
	int age;

	void DogEat()
	{
		printf("%s在吃狗粮\n", name);
	}
};

//C++封装 理念:  将属性和行为作为一个整体,来表现生活中的事物

//第二次理念: 将属性和行为  加以权限控制

void test01()
{
	struct Person p;
	strcpy(p.name, "老王");

	p.PersonEat();

	//p.DogEat();
}


//struct和class 区别?
//class 默认权限  私有权限  而 struct默认权限是 公共权限
//访问权限
// public  公共权限    成员 类内  类外 都可以访问	 
// private 私有权限    成员 类内  可以访问  类外  不可以访问  子类不可以访问父类的private权限内容
// protected 保护权限  成员 类内  可以访问  类外  不可以访问  子类可以访问父类的protected权限内容

class Person2
{
public:
	string m_Name; //公共权限

protected:
	string m_Car;  //保护权限

private:
	int  m_pwd;  //私有权限

public:

	void func()
	{
		m_Name = "张三";
		m_Car = "拖拉机";
		m_pwd = 123456;
	}

};

void test02()
{
	Person2 p;
	p.m_Name = "李四"; //公共权限  类外可以访问
//	p.m_Car = "劳斯莱斯"; //保护权限  类外访问不到
//	p.m_pwd = 123; //私有权限  类外不可以访问
}

int main(){
	test01();


	system("pause");
	return EXIT_SUCCESS;
}

6.4 尽量将成员属性设置为私有

将成员属性都设置为私有好处:自己可以控制读写权限
可以对设置内容,加有效性验证

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
#include <string>
class Person
{
public:
	//设置姓名
	void setName(string name)
	{
		m_Name = name;
	}
	//获取姓名
	string getName()
	{
		return m_Name;
	}

	//获取年龄
	int getAge()
	{
		return m_Age;
	}

	//设置年龄
	void setAge(int age)
	{
		if ( age < 0 || age > 150)
		{
			cout << "你这个老妖精" << endl;
			return;
		}
		m_Age = age;
	}

	//设置情人
	void setLover(string lover)
	{
		m_Lover = lover;
	}

private:
	string m_Name;  //姓名  可读可写
	int m_Age = 18;      //年龄  可读 可写(0 ~ 150之间)
	string m_Lover; //情人  只写
};

void test01()
{
	Person p;
	//可以将char * 隐式类型转换为 string
	p.setName("张三");
	cout << "姓名: " << p.getName() << endl;

	//获取年龄
	p.setAge(100);
	cout << "年龄: " << p.getAge() << endl;

	//设置情人
	p.setLover("苍井");

	//cout << "张三情人是:"<< p.m_Lover <<endl; //情人是只写权限  外部访问不到

}

//将成员属性都设置为私有好处:自己可以控制读写权限
//可以对设置内容 加有效性验证
int main(){
	test01();


	system("pause");
	return EXIT_SUCCESS;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值