目录
一、类的引入:
结构体struct在C语言中只是一个结构体,在C++中就升级成了“类”,这个就不只定义成员变量了,还可以定义函数。
比如,在C语言中实现的栈,在结构体中只能定义变量;若用C++的方式实现,那么在struct中可以定义函数。
如下就是用C++实现的有部分功能的栈。
struct Stack
{
int* a;
int capacity;
int top;
void Init(int defaultCapacity = 4)
{
a = (int*)malloc(sizeof(int) * defaultCapacity);
if (nullptr == a)
{
perror("stack malloc fail");
return;
}
capacity = defaultCapacity;
top = 0;
}
void Push(int x)
{
//扩容逻辑...
a[top++] = x;
}
void Destory()
{
free(a);
a = nullptr;
top = capacity;
}
};
二、类的定义:
类的定义用关键字class来进行定义:
class classname
{
//类的主体,有成员函数或者成员变量组成
};
在上面中class为类定义的关键字;classname为这个类的名字;注意最后的分号不要省略。
大括号中的内容为类的成员:类中的成员变量称为类的属性或成员变量;
类中的函数称为类的方法或者成员函数。
类的两种定义方式:
1、声明和定义全部放在类体中,注意:成员函数如果在类中定义,编译器可能会将它当做内联函数。
2、声明和定义分离(一般建议使用这种)注意:成员函数名前需要加上类名::
例如:
在头文件中进行声明函数:
#include<iostream>
using std::cout;
using std::endl;
class student
{
public:
char* _name;
int _age;
char* _sex;
void showstu();
};
在cpp文件中进行定义:
void student::showstu()
{
cout << _name << endl << _age << endl << _sex << endl;
}
三、类的访问限定符及封装:
1、限定符:
C++实现封装的方式:用类将对象的属性与方法结合在一块,让对象更加完善,通过访问权限选择性的将其接口提供给外部的用户使用。
访问限定符:
1、public(公有)
2.、protected(保护)
3、private(私有)
访问限定符理解:
1. public修饰的成员在类外可以直接被访问
2. protected和private修饰的成员在类外不能直接被访问(此处protected和private是类似的)
3. 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
4. 如果后面没有访问限定符,作用域就到 } 即类结束。
5. class的默认访问权限为private,struct为public(因为struct要兼容C)
2、封装:
定义:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互,通过访问权限来隐藏对象内部实现细节,控制哪些方法可以在类外部直接被使用。它本质上是一种管理,让用户更方便使用类。
四、类的作用域:
类所定义的新的作用域,在类外面被使用时,需要::来指明所属于的哪个类。
class Person
{
public:
void show();
private:
char _name[20];
char _sex[3];
int _age;
};
void Person::show()
{
cout << _name << endl << _sex << endl << _age << endl;
}
五、类的实例化:
用类这个类型创建一个对象的过程叫做类的实例化;
一个类可以实例化出多个对象,实例化出的对象占用实际的物理空间,存储类成员变量;
这个可以类似于有房子的图纸,将其建造成为一个真正的房子,可以用这个房子的图纸建造多个房子,各个房子占用不同的地方;
图纸里面不能住人就相当于不能直接定义类中的变量,需要进行实例化后再对其进行定义。
#include<iostream>
#include<string>
using std::cout;
using std::endl;
class student
{
public:
char _name[20];
int _age;
char _sex[10];
void showstu();
};
int main()
{
//student._age = 20; 没有实例化
student st;
st._age = 20;
cout << st._age << endl;
return 0;
}
六、类对象模型:
类对象在内存中存储方式:
只保存成员变量,成员函数放在公共的代码段。
如下图所示:
所以:一个类的大小,实际就是该类中”成员变量”之和,当然要注意内存对齐(对齐的规则和C语言结构体是一样的)
注意空类的大小,空类比较特殊,编译器给了空类一个字节来唯一标识这个类的对象,是为了占位,表示对象存在。
七、this指针:
我们从代码入手:
class Date
{
public:
void Init(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
void Print()
{
cout << _year << "-" << _month << "-" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1;
d1.Init(2023, 7, 4);
d2.Init(2023, 7, 5);
d1.Print();
d2.Print();
return 0;
}
如上代码中,是一个打印日期函数的,但是调用Print函数时,看着像不知道对象是什么(访问的是d1还是d2),但其实C++在编译的时候存在一个this指针,指向d1或者d2的地址,此时在调用时就用this指针来访问,这样的话,就可以明确地知道此时访问的是d1还是d2,实际上完整的代码如下所示:
ps:但是this操作在C++编译过程中自动完成的,所以在实际写代码的过程中不需要去写那些,写了反而会报错。
class Date
{
public:
void Init(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
void Print(Date* this)
{
cout << this->_year << "-" << this->_month << "-" << this->_day << endl;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1;
d1.Init(2023, 7, 4);
d2.Init(2023, 7, 5);
d1.Print(&d1);
d2.Print(&d2);
return 0;
}