设计类的代码框架
class 类名{
public: //公共权限
设置 成员属性
设置 成员函数
}
//使用类 创建对象 -> 实例化对象
类名 对象名
//通过对象来设置调用成员函数
类和对象的关系
类是对对象的抽象,对象是对类的实例。
案例一
设计一个圆的类,可以计算圆的周长
#include <string>
#include <iostream>
using namespace std;
const double pi = 3.14;
//设计一个类 求圆的周长
class Circle {//class代表生成一个类
public:
//成员属性
int r;
//成员函数
double calculateZC() {
return 2 * pi * r;
}
};
void test01() {
Circle c1; //创建一个圆的对象
c1.r = 2; //对成员属性赋值
cout << "圆c1的周长为:" << c1.calculateZC() << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
案例二
设计一个学生类,每个学生有姓名学号,可以对学生的信息进行输出
#include <string>
#include <iostream>
using namespace std;
class Student {
public:
//成员变量
string name;
long long studentId;
//使用成员函数修改成员变量
void setName(string s) {
name = s;
}
void setId(long long id) {
studentId = id;
}
//使用成员函数打印信息
void show() {
cout << "该学生的姓名为:" << name << endl;
cout << "该学生的学号为:" << studentId << endl;
}
};
void test02() {
//创建一个学生
Student s1; //实例化
s1.setName("冯世龙");
s1.setId(3220221637);
s1.show();
}
int main()
{
test02();
system("pause");
return 0;
}
内联函数
1)内联函数的引出
在C语言中经常把一些短并且执行频繁的计算写成宏,来避免函数调用的开销,宏函数举例:
#include <iostream>
using namespace std;
#define MyAdd(x, y) x+y;
void test() {
int ans = MyAdd(2, 3);
cout << "ans = " << ans << endl;
}
int main() {
test();
return 0;
}
在C++出现后,使用预处理宏会出现两个问题:
1.宏看起来像函数调用,但没有参数类型及返回值,实际会有隐藏的难以发现的问题,例如执行ans = MyAdd(2, 3)*2时会返回2+3*2;
2.宏函数没有作用域;
3.由于C++中预处理器不允许访问类的成员,所以预处理宏不能作类的成员函数。
为了继承宏的效率,没有函数调用的开销,又可以像普通函数那样可以进行参数、返回值的安全检查,又可以作为成员函数,C++引入了内联函数。
2)内联函数的基本概念
内联函数本身也是一个真正的函数,具有普通函数的所有行为,唯一不同之处在于内联函数会在适当地方像预定义宏一样展开,所以不需要函数调用的开销。
在普通函数前加上inline关键字,使其成为内联函数,但是必须将函数声明和函数体结合在一起。
内联函数避免了函数调用时的压栈、跳转、返回的开销,是用空间换时间。
3)类内部的内联函数
编译器会默认为类内部的成员函数加上inline关键字,定义为内联函数。
4)内联函数和编译器
C++中内联编译会有一些限制,以下情况编译器可能考虑不会将函数进行内联编译。
1.存在循环语句;
2.存在过多的条件判断语句;
3.函数体过于庞大;
4.对函数进行取址操作。
内联仅仅是给编译器的一个建议,但编译器不一定会接受这种建议,一个好的编译器会将小的、简单的函数自动设置为内联函数。
函数的默认参数及占位参数
C语言中没有默认参数和占位参数。
1)默认参数
C++在声明函数时可以为一个或多个参数指定默认参数值,在函数调用时如果没有传入参数,编译器会自动用默认值代替。
void test(int a = 10, int b = 20) { //直接在参数后面加上默认值
cout << "a + b = " << a+b << endl;
}
如果有一个位置有了默认参数,那么从这个位置开始,从左往右都要有默认参数。
2)函数的占位参数
void test2(int a, int) { //占位参数
}
如果有了占位参数,函数调用时必须要提供这个参数,但是用不到,函数体里面没有这个名,只有在重载++符号时会用到。
如果函数声明里面有了默认参数,函数实现里面必须没有。
函数重载
能使名字更方便使用,在C语言中,函数名必须是唯一的,在C++中允许出现同名的函数(必须在同一个作用域),但函数的参数个数或参数类型或参数顺序不同,这种现象成为函数重载。
1)函数重载的基本语法
无法按照返回值的类型不同对两个同名函数进行重载。
当函数重载遇到了默认参数,要注意避免二义性的问题。
引用的重载版本此时会调用(const int &a)。
void func(int &a) {
cout << "int &a" << endl;
}
void func(const int &a) {
cout << "const int &a" << endl;
}
void test(){
func(10);
}
2)函数重载的实现原理
在函数重载时,编译器内部会用不同的参数类型来修饰不同的函数名,用于内部自己区分。
extern "C" 浅析
C++中如果要调用C语言的方法,要加上 extern "C" 方法名,说明该方法按照C语言做链接。
C语言和C++语言封装的区别
C语言struct的成员函数要在结构体外进行定义,属性和行为分开处理了,类型检测不够。
C++语言的struct成员函数在结构体内进行定义,属性和行为绑定在一起,严格类型转换检测。
C++中struct和class是一个意思,唯一的不同是默认权限,struct默认权限是public。
成员属性设为私有
C++中class如果不声明权限,会默认权限是private,私有权限只能在类内部访问,类外部不可以访问;公共权限在类的内部和外部都可以访问;保护权限在类的内部和子类可以访问。
建议将成员函数都设为私有,自己提供公共的对外接口set或者get方法来进行访问。