预学先知
①面向对象和面向过程的初步认识
C语言是面向过程,关注的是过程,分析步骤,利用函数调用解决问题
C++是基于面向对象的,关注的是对象,将一件事拆成不同的对象,靠对象的交互完成
例子:
设计一个快递系统
面向过程:关注实现下单,信息整合,送单的过程,体现到代码–方法/函数
面向对象:关注实现类对象及类对象之间的关系,快递员,商家,用户之间的关系 --类的设计及类之间的关系
②C++是基于面向对象:面向过程和面向对象混编。
原因:C++兼容C
然而JAVA是纯面向对象:只有面向对象
③C++对结构体进行了升级
一方面struct 在C++中升级成了类
C++类跟结构体不同的是除了可以定义变量,还可以定义方法/函数
#include<iostream>
#include<string.h>
#include<stdlib.h>
#include<cstdio>
using namespace std;
//struct/class
//C++兼容C中结构体的用法
//同时Struct在c++中升级成了类
//C++在类中还可以定义方法/函数
struct Student {
//成员变量
char _name[10];
int _age;
int _id;
//成员方法
void Init(const char* name, int age, int id) {
//避免冲突,将前面改成_
strcpy(_name, name);
_age = age;
_id = id;
}
void Print() {
cout << _name << " " << _age << " " << _id << endl;
}
};
int main() {
struct Student s1 = {
"xpc",18,7};//兼容C
Student s2 = {
}; //升级成为类,Student是类名,也是类型
s1.Print();
s2.Init("zkx", 20, 11);
s2.Print();
return 0;
}
类和对象
1.类的访问限定符
了解class 和 struct 定义的区别,class 里面成员变量默认是私有的,而struct默认是公有(public)
最好不要使用默认限定,自己定义private和public(访问限定符)
我们来定义第一个类~
封装是一种更好的管理模式
①数据和方法都封装到类里面
②可以给你访问定义成共有,不想给你访问定义成私有或者保护
不封装是一种自由管理
class Student {
private:
//成员变量
char _name[10];
int _age;
int _id;
public:
//成员方法
void Init(const char* name, int age, int id) {
//避免冲突,将前面改成_
strcpy(_name, name);
_age = age;
_id = id;
}
void Print() {
cout << _name << " " << _age << " " << _id << endl;
}
};
int main() {
struct Student s1; //兼容C
Student s2; //升级成为类,Student是类名,也是类型
return 0;
}
注意,如果加了inline或者直接在类内定义(10几行内),编译器可能将这个方法当成内联函数处理
2.类的作用域
类定义了一个域
3.类大小的计算
只保存成员变量,成员函数放在公共代码区
为什么成员函数不放进来计算?
原因:每个对象中都有独立的成员变量,不同对象调用成员函数,调的是同一个,没有必要每个对象都保存一份
结论:计算类和类对象的大小,只看成员变量,考虑内存对齐,C++内存对齐规则跟C语言一致
另外,空类会给1byte,不存储有效数据,只是为了占位表示对象的存在
sizeof 类 算出的是实例化对象的大小,而不是类是多大
补充C语言的内存对齐规则
4.this指针
既然成员方法不保存在类的实例对象内,那这些不同的对象调用同样的方法为什么会取得他们各自的值??
那是因为省略了隐藏的this指针!
①调用成员函数时,不能显示传实参给this
②定义成员函数时,也不能显示声明形参this
③在成员函数内部,我们可以显示使用this
问题1:this是存在哪的?
一般情况下是存在栈(形参),有些编译器会放到寄存器中,如VS2019,ecx
问题2:
这道题选C
如果有人觉得是空指针错了,那不行,空指针是运行时错误,编译是检查不出来的
问题3:
选B
5.默认成员函数
1.构造函数
不然既有全缺省又有无参,语法上可以同时存在,但是如果同时存在,就会产生二义性
class Date {
public:
/*Date() {
_year = 2022;
_month = 2;
_day = 8;
}
Date(int year, int month, int day) {
_year = year;
_month = month;
_day = day;
}*/
//推荐使用全缺省或者半缺省,比较好用
Date(int year = 2022, int month = 2, int day = 8) {
_year = year;
_month = month;
_day = day;
}
private:
int _year;
int _month;
int _day;
};
int main() {
Date d1;
Date d2(2022);
Date d3(2022, 1);
Date d4(2022, 1, 15);
return 0;
}
C++把类型分成两类:内置类型(基本类型),自定义类型
内置类型:int/char/double/指针/内置类型数组等
自定义类型:struct/class定义的类型
我们不写编译器默认生成构造函数,对于内置类型不做初始化处理
对于自定义类型成员变量会去调用它的默认构造函数(不用参数就可以调的)初始化
如果没有默认构造函数就会报错
任何一个类的默认构造函数就是–不用参数就可以调用
有三个,全缺省,无参,我们不写编译器默认生成的
总结:C++我们不写编译器默认生成构造函数,设计得不好,没有对内置类型和自定义类型统一处理
不处理内置类型的成员变量,只处理自定义类型成员变量
#include<iostream>
#include<string.h>
#include<stdlib.h>
#include<cstdio>
using namespace std;
class A {
public:
A(int a = 0){
cout << "a()" << endl;
_a= a;
}
private:
int _a = 0;
};
class Date {
public:
private:
int _year;
int _month;
int _day;
A _aa;
};
int main() {
Date d1;
return 0;
}
构造函数本质用来初始化
构造函数的初始化列表
用: 和 , 分割
弄懂声明和定义:声明是一种承诺,没有实现,没有开空间,类型+变量属于是声明,定义是要开空间,要给值