并非从0开始的c++ day14

并非从0开始的c++ day14

  • 函数的默认参数
    • 函数的默认参数的注意事项
  • 占位参数
    • 占位参数和默认参数混搭
  • 函数参数传递的三种方式
    • 值传递
    • 指针传递
    • 引用传递
  • 函数重载
    • 函数重载的条件
    • 调用重载函数的注意
    • 函数重载和函数默认参数一起使用,需要注意二义性
    • 函数的返回值不作为函数的重载的条件
    • 函数重载的原理
  • C++调用C语言的函数
  • 类和对象的概念
    • 类的封装
      • 为什么要有封装
      • 类的权限
    • 尽量把属性设置为私有权限
    • C++中类和结构体的区别

函数的默认参数

  1. 函数的默认参数就是给函数的形参赋值
int myFunc(int a, int b = 0)//int b = 0;这就是函数的默认参数,不一定是0
{
	return a + b;
}

void test01()
{
	//函数的默认参数的作用
	//当函数内常要用到的形参的某个值,但偶尔要使用其他值
	//增加函数的灵活性
	cout << myFunc(10, 20) << endl;
	cout << myFunc(10) << endl;
}

函数的默认参数的注意事项

  1. 函数的默认参数后面的参数必须都是默认参数
//int myFunc2(int a, int b = 0, int c)  err
int myFunc2(int a, int b = 0, int c = 2,int d = 3)
{
	return a + b + c + d;
}
  1. 函数的声明和实现不能同时有函数的默认参数
void myFunc3(int a, int b );
void myFunc3(int a, int b = 0)
{

}

尤其要注意头文件和源文件的函数的冲突,一般都是在源文件中加入默认参数

占位参数

函数的占位参数,占位参数在后面运算符重载时区分前加加或后加加时

void func(int a ,int = 10)//占位参数也有默认值
{
	
}

void test02()
{
	func(10);
}

占位参数和默认参数混搭

void func2(int=10,int a = 20)
{

}

void test03()
{
	func2();
	func2(10);
	func2(10, 30);
}

默认参数后续都必须是默认参数,占位参数没有这个限制

函数参数传递的三种方式

值传递

void swap(int a, int b)
{
	int temp = a;
	a = b;
	b = temp;
}

指针传递

void swap2(int* a, int* b)
{
	int temp = *a;
	*a = *b;
	*b = temp;
}

引用传递

void swap3(int& a, int& b)
{
	int temp = a;
	a = b;
	b = temp;
}

上述代码中,值传递是不交换a和b的值,指针传递和引用传递都改变值,但是两者的原理并不一致,参考之前的笔记

函数重载

函数重载是:允许函数名相同,这种现象叫函数重载
函数重载的作用是:为了方便使用函数名
函数重载的条件是:

  • 同一个作用域内
  • 参数个数不同
  • 参数类型不同
  • 参数顺序不同

函数重载的条件

//参数的个数不同
void func()
{
	cout << "func()" << endl;
}

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

//参数的类型不同
void func(char c)
{
	cout << "func(char c)" << endl;
}

//参数的顺序不同
void func(int a, double b)
{
	cout << "func(int a, double b)" << endl;
}

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

调用重载函数的注意

严格的类型匹配,如果类型不匹配,那么尝试转换,转换成功就调换,失败就报错

void test01()
{
	int a = 10;
	double b = 3.14;
	func();
	//func(b);  double 转换不了称为int 或者char 
	func(a, b);
	func(b, a);
	char c = 'c';
	func(c);//char转换int 成功,调用int参数的函数
}

函数重载和函数默认参数一起使用,需要注意二义性

void myFunc(int a, int b = 0)
{
	cout << "myFunc(int a,int b = 0)" << endl;
}

void myFunc(int a)
{
	cout << "myFunc(int a)" << endl;
}

void test02()
{
	//myFunc(10);//err 二义性问题,不知道调用哪个函数
}

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

编译器是通过调用函数时,传入的参数来判断调用重载的哪个函数,我们调用函数时,不需要写返回值,所以返回值不能成为函数重载的条件

函数重载的原理

函数重载的原理是在汇编时,给各个函数取别名,C语言不能重载的原因就是没有给函数取别名

C++调用C语言的函数

C++的函数在汇编时,会给函数取别名,C语言的不会,这时,如果C++来调用C语言的函数,C++会去找去了别名的函数,但是C语言没有取别名,这时会报错

#ifdef __cplusplus
extern "C"
{
#endif

	void func();
	

#ifdef __cplusplus
}
#endif

这是告诉C++编译器,找下面的函数,要以C语言的方式去寻找

类和对象的概念

  1. 类是自定义数据类型,是C语言的结构体进化而成的
  2. 对象是类实例化出的,用数据类型定义一个变量

类的封装

  1. 封装是吧属性(变量)和方法(函数)封装到类内,然后给这些数据赋予权限

为什么要有封装

  1. 防止乱调用函数和变量,出现错误
  2. 维护代码更方便

类的权限

并非从0开始的c++ day14_第1张图片
子类的类内可以访问父类的保护权限的成员

class Maker
{
public://共有权限
	void set(string Name, int Id)
	{
		id = Id;
		name = Name;
	}
	void printMaker()
	{
		cout << "id = " << id << " name = " << name << endl;
	}
private://私有
	int id;
	string name;


protected:
	int a;
};

class Son :public Maker
{
	void func()
	{
		a = 20;//子类的类内可以访问父类的保护权限的成员
	}
};
//类外不能访问私有权限的成员
//类外可以访问共有权限的成员
//类外不能访问保护权限的成员
//子类的类内可以访问父类的保护权限的成员
//类内是没有权限之分的

void test()
{
	Maker m;
	m.set("zero", 1);
	m.printMaker();
}

尽量把属性设置为私有权限

  1. 可以控制属性的读写权限
  2. 可赋予客户端访问数据的一致性
  3. 可以保护属性的合法性
class Maker
{
public:
	//写
	void setName(string Name)
	{
		name = Name;
	}
	//读
	string getName()
	{
		return name;
	}
	//写
	void setAge(int Age)
	{
		//可以保护属性的合法性
		if (Age > 0 && Age < 100)
			age = Age;
		else
			cout << "Age is error number!" << endl;
	}
	//读
	int getId()
	{
		return id;
	}
private:
	string name;
	int age;
	int id;
public:
	int func;
};

C++中类和结构体的区别

结构体的默认权限是公有的,类的默认权限是私有的

你可能感兴趣的:(c++,开发语言)