该笔记目录部分链接
本小节目录部分
-
01.引用的使用场景(重点)
-
02.常量引用(了解)
-
03.内联函数(了解)
-
04.函数的默认参数(重点)
-
05.函数的占位参数(了解)
-
06.函数参数传递的三种方式
-
07.设计求圆的周长
-
08.设计学生类
-
09.函数重载(重点)
-
10.函数重载的原理(重点)
-
11.C++调用C语言的函数(重点)
-
12.类和对象的概念(重点)
-
13.类的封装(重点)
-
14.课堂练习
-
15.类和结构体的区别(了解)
01.引用的使用场景(重点)
1.引用作为函数参数
//1.引用作为函数参数
void func(int &a, int &b)
{
int sum = a + b;
cout << "sum=" << sum << endl;
}
void test01()
{
int a = 10;
int b = 20;
func(a, b);
}
2.引用作为函数的返回值
//2.引用作为函数的返回值
int& func2()
{
int b = 10;//注意1:不要返回局部变量的引用
int &p = b;
return p;
}
int &func3()
{
static int b = 10;
return b;
}
void test02()
{
int &q = func2();
q = 100;
cout << q << endl;
func2() = 200;
cout << q << endl;
////---------上面的代码是错误,只是编译器没有检测出来
cout << "func2="<<func2() << endl;
func3() = 100;//注意2:如果要函数当左值,那么该函数必须返回引用
cout << "func3()=" << func3() << endl;
}
02.常量引用(了解)
int main()
{
//普通引用
int a = 10;
int &ref = a;
ref = 20;
//int &ret2 = 10;//不能给字面量取别名 err
const int &ref3 = 10;//可以给const修饰的引用赋予字面量
//const修饰符修饰的引用的原理
//编译器会把上面的代码变为:int tmp=10;const int &ref3=tmp;
//ref3 = 200;err
//bool类型
//bool类型定义的变量只有两个值,true和false,真和假,1和0
bool is = 0;//注意:is的值除0以外,都是真
if (is)
{
cout << "真" << endl;
}
else
{
cout << "假" << endl;
}
system("pause");
return EXIT_SUCCESS;
}
03.内联函数(了解)
1.宏函数的缺陷
#define ADD(x,y) x+y
//在普通函数前面加上inline是向编译器申请成为内联函数
//注意:加inline可能成为内联函数,可能不成为内联函数
inline int Add(int x, int y)
{
return x + y;
}
void test()
{
//10+20*2
int ref = ADD(10, 20) * 2;
cout << "ref=" << ref << endl;
int ref2 = Add(10, 20) * 2;
cout << "ref2=" << ref2 << endl;
}
#define COMAPD(x,y) ((x)<(y)?(x):(y))
inline int func(int x, int y)
{
return x < y ? x : y;
}
void test02()
{
int a = 1;
int b = 3;
// ((++a)<(b)?(++a):(b))
//cout << "COMAPD(x,y)=" << COMAPD(++a, b) << endl;//3
cout << "func=" << func(++a, b) << endl;//2
}
2.什么情况不会成为内联函数
1.存在过多的条件判断语句
2.函数体过大
3.对函数进行取址操作
4.存在任何形式的循环语句
3.内联函数的好处
1.有宏函数的效率,没有宏函数的缺点
2.类的成员函数默认加上inline
4.在普通函数前面加上inline是申请成为内联函数
04.函数的默认参数(重点)
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;
}
2.函数的默认参数的注意事项
//注意1:函数的默认参数后面的参数必须都是默认参数
int myFunc2(int a, int b = 0, int c=2,int d=3)
{
return a + b + c + d;
}
//注意2:函数的声明和实现不能同时有函数的默认参数
void myFunc3(int a, int b);
void myFunc3(int a, int b = 0)
{
}
05.函数的占位参数(了解)
//函数的占位参数,占位参数在后面运算符重载时区分前加加或后加加
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);
}
06.函数参数传递的三种方式
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
//值传递
void swap(int a, int b)
{
int tmp = a;
a = b;
b = tmp;
}
//指针传递
void swap2(int *a, int *b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
//引用传递
void swap3(int &a, int &b)//int &a=a,int &b=b;
{
int tmp = a;
a = b;
b = tmp;
}
//打印
void myprint(int &a,int &b)
{
cout << "a=" << a << " b=" << b << endl;
}
int main()
{
int a = 10;
int b = 20;
swap(a, b);
myprint(a, b);//10,20
swap2(&a, &b);
myprint(a, b);//20,10
a = 10;
b = 20;
swap3(a, b);
myprint(a, b);//20,10
system("pause");
return EXIT_SUCCESS;
}
07.设计求圆的周长
#include<iostream>
#include<string>
using namespace std;
//自定义的数据类型
//设置圆的类
class Circle
{
public:
//设置半径的长度
void setR(double r)
{
mR = r;
}
//计算圆的周长
double getL()
{
return 2 * 3.14*mR;
}
public://公有权限
double mR;//成员变量,成员属性
};
void test()
{
//数据类型定义变量
//类实例化对象
Circle c;
c.setR(100);
cout << "圆的周长=" << c.getL() << endl;;
}
int main()
{
test();
system("pause");
return EXIT_SUCCESS;
}
08.设计学生类
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
#include<string>
class Student
{
public://公有
//设置名字
void setName(string Name)//成员方法,成员函数
{
name = Name;
}
//设置ID
void setId(int Id)
{
id = Id;
}
void myprint()
{
cout << "姓名:" << name << "\n学号:" << id << endl;
}
private://私有权限
string name;//成员属性
int id;//成员属性
};
int main()
{
Student s;
s.setName("贝吉塔");
s.setId(1);
s.myprint();
system("pause");
return EXIT_SUCCESS;
}
09.函数重载(重点)
1.函数重载是:允许函数名相同,这种现象叫函数重载
2.函数重载的作用:是为了方便使用函数名
3.函数重载的条件:同一个作用域,参数的个数不同,参数的顺序不同,参数的类型不同
//参数的个数不同
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;
}
4.调用重载函数的注意:
严格的类型匹配,如果类型不匹配,那么尝试转换,转换成功就掉用,失败就报错
void test01()
{
int a = 10;
double b = 3.14;
func();
//func(b);// err double转换不了成为int或char
func(a, b);
func(b, a);
char c = 'c';
func(c);//char转换int成功,调用int参数的函数
}
5.函数重载和函数的默认参数一起使用,需要注意二义性问题
//函数重载和函的默认参数一起使用
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,二义性问题,不知道调用哪个函数
}
6.函数的返回值不作为函数重载的条件
编译器是通过你调用函数时,传入的参数来判断调用重载的哪个函数,我们调研函数时不需要写返回值,所以返回值不能成为函数重载的条件
10.函数重载的原理(重点)
1.函数重载的原理是在汇编时,给各个函数取别名,C语言不能重载的原因是没有取别名
2.生成汇编文件:gcc -S test.c -o test.s g++ -S test.cpp -o test2.s
3.查看内容:type 文件名
11.C++调用C语言的函数(重点)
1.C的函数在汇编时,会给函数取别名,C语言的不会,这时,如果C来调用C语言的函数,C++会去找取了别名的函数,但是C语言没有取别名,这时会出错
test.h文件中
//这是告诉C++编译器,找下面的函数,要以C语言的方式去寻找
#ifdef __cplusplus
extern "C"
{
#endif
void func();//C语言的函数声明
#ifdef __cplusplus
}
#endif
12.类和对象的概念(重点)
1.类是自定义数据类型,是C语言的结构体进化而成的
2.对象是类实例化出的,用数据类型定义一个变量
class Maker//这个是类
{
public:
int a;//成员属性(成员变量)
void func()//成员方法(成员函数)
{
cout << "func" << endl;
}
};
int main()
{
Maker m;//m就是对象
system("pause");
return EXIT_SUCCESS;
}
13.类的封装(重点)
1.封装是把属性(变量)和方法(函数)封装到类内,然后给这些数据赋予权限
2.为什么要有封装
1.防止乱调用函数和变量,出现错误
2.维护代码更方便
3.权限
//封装:1,把属性和方法放到类中,2.给这些数据赋予权限
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("小花",1);
m.printMaker();
}
4.尽量把属性设置为私有权限
1.可以控制属性的读写权限
2.可赋予客户端访问数据的一致性
3.可以保护属性的合法性
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
#include<string>
class Maker
{
public:
//写
void setName(string Name)
{
name = Name;
}
//读
string getName()
{
return name;
}
//写
void setAge(int Age)
{
//可以保护属性的合法性
if (Age > 0 && Age < 120)
{
age = Age;
}
}
//读
int getId()
{
return id;
}
private:
string name;
int age;
int id;
};
int main()
{
Maker m;
m.setAge(1000);
system("pause");
return EXIT_SUCCESS;
}
14.课堂练习
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
#include<string>
//自定义数据类型
class Maker
{
public:
void Init()//初始化函数
{
name = "翠花";
age = 18;
}
//set get方法
void setN(string mName)
{
name = mName;
}
string getN()
{
return name;
}
void setA(int mAge)
{
if (mAge >= 0 && mAge <= 100)
{
age = mAge;
}
}
int getA()
{
return age;
}
//打印方法
void printMaker()
{
cout << "name:" << name << " age:" << age << endl;
}
private:
string name;
int age;
};
int main()
{
//Maker是类,m的对象
Maker m;
m.Init();
m.printMaker();
m.setN("美丽");
m.setA(30);
m.printMaker();
cout << "name:" << m.getN() << " age:" << m.getA() << endl;;
system("pause");
return EXIT_SUCCESS;
}
15.类和结构体的区别(了解)
结构体的默认权限是公有的,类的默认权限是私有的