1.类和对象
1.1.类
类是一种用户自定义的数据类型,它描述了一组具有相同属性和行为的对象。类的定义通常包括以下部分:
- 类名:用于标识类的名称,应该具有描述性且符合命名规范。
- 成员变量(属性):描述类的状态或特征,通常是变量。
- 成员函数(方法):描述类的行为或操作,通常是函数。
cpp
class Car {
public:
std::string brand;
std::string color;
void accelerate() {
std::cout << brand << " car is accelerating." << std::endl;
}
void brake() {
std::cout << brand << " car is braking." << std::endl;
}
};
1.2.对象的创建和使用
对象是类的一个具体实例。可以通过以下方式创建对象:
cpp
int main() {
Car car1;
car1.brand = "Toyota";
car1.color = "red";
Car car2;
car2.brand = "Honda";
car2.color = "blue";
car1.accelerate();
car2.brake();
return 0;
}
其中,类和对象中有访问限定符public(公有),protected(保护),private(私有),
其中class默认为private,struct默认为public。
public
成员可以在类的外部直接访问。private
成员只能在类的内部访问。protected
成员可以在类的内部和派生类中访问。
1.3面对对象的特性
封装
继承
多态
其中封装为:将数据和操作数据的方法进行有机结合,隐蔽对象的属性和实现细节,仅对外公开接口来和对象进行交互。(封装本质是一种管理,让用户更方便使用类)。
cpp
class Car {
private:
std::string brand;
std::string color;
public:
Car(std::string b, std::string c) {
brand = b;
color = c;
}
void setBrand(std::string b) {
brand = b;
}
void setColor(std::string c) {
color = c;
}
std::string getBrand() {
return brand;
}
std::string getColor() {
return color;
}
void accelerate() {
std::cout << brand << " car is accelerating." << std::endl;
}
void brake() {
std::cout << brand << " car is braking." << std::endl;
}
};
在这个例子中,brand
和color
成员变量被声明为private
,只能通过公有成员函数setBrand
、setColor
、getBrand
和getColor
来访问。
1.4this指针
this
指针是一个特殊的指针,它指向正在被调用成员函数的对象。
cpp
class MyClass {
private:
int x;
public:
void setX(int x) {
// 使用 this 指针区分成员变量和局部变量
this->x = x;
}
};
注意:
1.实参和形参的位置不能显示编写,反而编译器会自己加。
2.在类里面可以使用。
3.this指针为形参,存在栈当中。
2.类的6个默认成员函数
默认成员函数:用户没有显示实现,编译器会生成的成员函数。
2.1构造函数(不需要自己初始化)
构造函数:是一种特殊的成员函数,用于在创建对象时初始化对象的数据成员。
主要任务:不构造空间,而是初始化对象。
特征:
1.函数名需和类名相同。
2.无返回值。
3.对象实例化是编译器自动调用对应的构造函数。
4.构造函数可以重载(多个构造函数,多种初始化方式)。
注:编译器自动生成构造函数,,对内置成员变量不做处理。
C++类型分为内置类型,如int char和自定义类型,如class struct。
cpp
class MyClass {
private:
int x;
double y;
public:
MyClass() : x(0), y(0.0) {}
MyClass(int a, double b) : x(a), y(b) {}
//上述是一种简写方式
MyClass(int a, double b)
{
x = a;
y = b;
}
//这种方式较上面一个比较繁琐,但好理解。
};
int main()
{
MyClass obj1; // 调用无参构造函数
MyClass obj2(10, 3.14); // 调用带参数的构造函数
}
默认构造函数和拷贝构造函数
- 默认构造函数
- 如果没有显式定义任何构造函数,编译器会自动生成一个默认构造函数。默认构造函数没有参数,它将对象的成员变量初始化为默认值。
- 拷贝构造函数
- 拷贝构造函数是一种特殊的构造函数,它接受一个同类型的对象作为参数,并使用该对象来初始化新创建的对象。
2.2析构函数(不需要自己释放空间)
析构函数:是一种特殊的成员函数,用于在对象被销毁时执行一些清理操作。
主要任务:与构造函数相反,不是对本身的销毁,而是对象在销毁时会自动调用析构函数来完成对象中资源的清理工作。
特征:
1.析构函数名是类名前加上字符~。
2.无参数无返回值类型。
3.一个类只能有一个析构函数,若未显示定义,系统自动生成默认的析构函数。
4.析构函数不能重载。
5.对象生命周期结束时,C++编译系统自动调用析构函数。如~strack()。
cpp
class ResourceHolder {
private:
int* data;
public:
ResourceHolder() {
data = new int[10];
}
~ResourceHolder() {
delete[] data;
}
};
注意事项
- 谨慎处理资源释放
- 在析构函数中释放资源时,要确保资源已经被正确分配。如果在对象创建过程中资源分配失败,析构函数不应尝试释放未分配的资源。
- 避免异常抛出
- 析构函数中应尽量避免抛出异常,因为如果析构函数抛出异常,可能会导致程序异常终止或出现未定义的行为。如果在析构函数中必须处理可能抛出异常的操作,可以在析构函数内部捕获异常并进行适当的处理。