结构体:
结构体是一种用户定义的数据类型,它允许你将不同类型的数据组合成一个单一的复合类型。
结构体通常用于封装一组相关的数据项,以形成一个逻辑单元。
声明一个结构体:
语法:
struct 结构体名
{
//数据成员
//成员函数
};
eg:
struct sum
{
int x; // 数据成员
int y; // 数据成员
void out()
{
cout << x+y << endl;
} // 成员函数
};
结构体与类(class)相似,结构体可以包含数据成员(变量)和成员函数(方法)。
结构体的定义方式:
结构体的定义方式有五种方式(举一个例子清晰可以看出)
标准定义与实例化分离:
struct Person
{
string name;
int age;
};
int main()
{
Person person1;
}
同时定义与实例化:
struct Person
{
string name;
} person1, person2;
匿名结构体定义并实例化:
struct
{
string name;
} anonymousPerson = {"John", 30};
使用typedef定义类型别名:
typedef struct
{
string name;
} PersonType;
int main()
{
PersonType person3;
return 0;
}
C++11引入的using关键字定义类型别名:
using PersonType = struct
{
string name;
};
int main()
{
PersonType person4;
return 0;
}
类:
类和结构体很相似!
在C++中,结构体和类的主要区别在于默认的访问权限:
结构体的成员默认是公有的(public),而类的成员默认是私有的(private)。
在C++中,类的成员(包括数据成员和成员函数)有三种访问权限:公有(public)、私有(private)和保护(protected)。
三种访问权限:
公有(public):
公有成员可以在任何地方被访问,包括类的外部、类的内部以及派生类中。
如果一个成员函数或数据成员被声明为 public,那么所有知道这个类的代码都可以直接访问这些成员。
私有(private):
私有成员只能在其所在的类的内部访问,不能在类的外部或者派生类中直接访问。
使用 private 关键字声明的成员主要是为了封装性,防止外部代码直接修改类的内部状态,保证数据安全性和逻辑完整性。
保护(protected):
保护成员可以在类的内部以及其派生类中访问,但在类的外部无法直接访问。
protected 成员用于实现继承中的访问控制,允许派生类访问基类的部分私有细节,但又不让外界随意访问。
类的定义和使用:
举一个例子:
#include<iostream>
class currrent_data
{
int year{},month{},day{};
public:
void set(int a,int b,int c);
void out();//定义成员函数
};
void currrent_data::set(int a,int b,int c)
{
year=a;
month=b;
day=c;
}
void currrent_data::out()
{
std::cout<<"year="<<year<<" "<<"month="<<month<<" "<<"day="<<day;
}
int main()
{
currrent_data today;
today.set(2024,4,7);
today.out();
return 0;
}
构造函数和析构函数:
构造函数
定义:
构造函数是一种特殊的方法,其名称与类名完全相同,没有返回类型(甚至不能声明为void)。构造函数的主要目的是初始化新创建的对象。
用途:
当创建类的实例(对象)时,构造函数会被自动调用,用于设置对象内部的数据成员到初始状态或执行必要的初始化操作。
特点:
可以重载,即一个类可以有多个构造函数,每个构造函数可以接受不同数量或类型的参数。
编译器会为没有显式定义构造函数的类生成一个默认构造函数(如果类中没有自定义的构造函数并且所有数据成员都有默认构造函数的话)。
委托构造函数
委托构造函数是C++11引入的一个特性,它允许一个类的构造函数调用同一个类的另一个构造函数来执行其初始化工作。
委托构造函数的语法是在构造函数的初始化列表中调用另一个构造函数。这通常用于减少代码冗余,特别是在当多个构造函数共享相同的初始化代码时。委托构造函数可以是显式委托给另一个同类的构造函数,也可以是隐式委托给默认构造函数。
class MyClass
{
private:
int x;
double y;
public:
// 主要的构造函数,接受两个参数并执行初始化
MyClass(int val, double val2) : x(val), y(val2) {}
// 委托给另一个接受两个参数的构造函数
MyClass(int val) : MyClass(val, 0.0) {}
};
析构函数
定义:
析构函数也是一种特殊的方法,其名称是在类名前添加波浪线(tilde ~)作为前缀,同样没有返回类型。
用途:
析构函数会在对象生命周期结束时自动调用,主要用于释放对象可能占用的资源,例如动态分配的内存、关闭文件句柄、解除信号量绑定等,完成所谓的“清理工作”。
特点:
析构函数不能重载,一个类只有一个析构函数。
若用户没有自定义析构函数,编译器会生成一个默认的析构函数,这个默认析构函数通常是空的,不做任何清理工作。
当对象离开作用域(如函数结束、栈上的对象销毁、delete一个动态分配的对象)时,析构函数会被自动调用。
this指针
含义:
this指针隐含地作为每个非静态成员函数的第一个参数传递给函数,但在函数声明或定义时并不需要写出this参数。它提供了对当前对象的访问,允许成员函数直接引用和修改对象的数据成员。
类型:
this指针的类型是指向类类型的常量指针,对于类ClassName的成员函数而言,this的类型是ClassName* const,这意味着你可以通过this来读取或修改对象的成员变量,但不能改变this指针本身的值。
使用场景:
解决同名成员变量和局部变量之间的命名冲突。
返回当前对象的引用或指针。
在成员函数内部调用其它成员函数或者访问成员变量。
class FFF
{
public:
int x;
void setX(int newX)
{
this->x = newX; // 使用this指针明确指定成员变量x
}
void printX()
{
std::cout << "x = " << this->x << ", address: " << this << std::endl;
}
};
int main()
{
FFF obj;
obj.setX(10);
obj.printX(); // 输出x的值和对象obj的地址
return 0;
}
*this就是this指向的对象
类的声明与定义需要注意的点:
有三种类型
1.类的定义在主函数前(这个是最平常的一个类型)
class 类名
{
// 类的内容
};
2.类的定义在主函数后
如果是这个类型
需要将类的声明放在主函数前,与函数定义一样
class 类名;
int main()
{
}
class 类名
{
};
3.类的定义在不同的源文件
// MyClass.h
class MyClass
{
//类的内容
};
// main.cpp
#include "MyClass.h"
int main()
{
return 0;
}
class定义在头文件中主函数需要使用的话那就需要包含该文件