C++ ———— 2(类相关)

一、类——class

类:是对象的抽象,对象是实例化的对象

对象:对象要占内存空间,类不会占内存空间

类的一般形式

class
{
    public:
    //公有区域
    protected:
    //保护区域
    private:
    //私有区域
}

类实例化的方法:

类名 对象名;		//栈区对象
类名 指针名 = new 类名;	//堆区对象

二、构造函数

构造函数结构

class 类名{
    public:
    	/**
    	构造函数:
    		1.无返回值 
    		2.定义时,系统自动调用 
    		3.不能手动调用构造函数
    		4.如果没有实现构造函数,编译器会自动生成一个无参构造
    	*/
    	类名(参数)
        {
            函数体
        }
}

构造函数参数传递

List obj(20);		//显式传递参数给构造函数
List obj2 = 20;		//隐式传递参数
List *p = new List(20);	//正常传递参数给构造函数

三、析构函数

析构函数:专门用来回收对象的资源,函数名和类名一致,在函数名前加~

特征:

​ 没有返回值、没有参数、无法重载

​ 可以手动调用析构函数,也可以在生命周期结束时被系统自动调用(注意double free)

~List()
{
 if(nullptr != p)	//注意判断要delete的空间是否已经被释放
 {				 	//避免造成double free
		delete[] p;
     p = nullptr;
 }
}

析构函数问题

析构函数是释放资源时自动调用,在如下代码中,代码的执行是在系统栈区内的,所以将对象进行压栈处理,这就使最后释放资源调用析构函数的时候的顺序有所改变(遵循栈的先进后出原则)

class A
{
    public:
        A(int a)
        {
            cout << "A" << a << endl;
            this->num = a;
        }       //普通构造函数
        ~A()
        {
            cout << "~A" << this->num << endl;
        }       //析构函数
    private:
        int num;
};

int main()
{
    A a(10);
    A b(20);
    return 0;
}

alt

四、特殊构造——拷贝构造

新构造对象的时候,初始化的等式右值为已存在的同类型对象,系统会调用拷贝构造函数

List b = a;		//a为已存在的List对象,b为新对象

拷贝构造仍然是构造函数,我们没有声明实现,编译器会自动生成,自动生成的拷贝构造函数是直接对已存在对象的数值依次赋值给新对象(浅拷贝)

当类中有new出来的成员就会出现double free问题,此时我们必须要重新实现拷贝构造进行深拷贝

//拷贝构造eg
List(const List &obj)
{
	this.index = obj.index;
    this.max = obj.max;
    this.arr = new Type[max];
    for(int i = 0 ; i < this.index ; i++ )
		this.arr[i] = obj.arr[i];
}

五、特殊构造——移动构造

C++ 11 中新的语法,如果给一个新对象赋值临时对象,此时会调用移动构造来实现。

移动构造形式:

类名(类名 &&obj)
{
    //移动构造
}

g++编译器 默认会优化掉 临时对象 ,所以一般不会用到移动构造

六、临时对象的问题

函数返回的对象、无名对象都是临时对象。

C++默认禁止临时对象产生,如果需要允许临时对象产生,需要添加编译开关:

g++ xxx.cpp -fno-elide-constructors

七、static成员

静态成员属于class类 不属于对象

可以将类的成员声明成静态的(关键字static修饰的成员函数或成员变量)

通过类名和作用域解析运算符来调用静态成员

类名:静态成员名称

静态成员没有对象的this指针

静态成员不和具体的对象关联,也不能直接访问类的其他成员

static修饰成员变量:它仍然受到类的访问权限限制,初始化只能在类外

static修饰成员函数:它仍然受到类的访问权限限制,静态成员函数只能访问静态成员。

八、const成员变量

1.const修饰成员变量

const作用:常量化

const修饰成员数据:表示类的成员数据只读

const成员数据(初始化):只能使用初始化列表来初始化(初始化列表只在构造函数内可用)

class A
{
    public:
    A(){}
    A(int a):val(val),b(a)    //:val(a) 初始化列表 只在构造函数内有这个语法  在构造函数调用之前进行赋值操作
    {
        //this->val = val;      //error val是const修饰的不能被修改
    }
    private:
    const int val;
    int b;
}

2.const修饰成员函数

const修饰类的成员函数:表示该函数不会修改类的成员数据

一般形式:

返回值类型	成员函数名(形参列表) const
{
    //函数体
}

<tips>const修饰的成员函数内部不能修改成员数据,内部也不能调用类的非const成员函数

3.const修饰类对象

const修饰类对象:表示该对象是常对象

常对象:只能访问常成员

一般形式:

const 类型 对象名;
类名 const 对象名;

练习:

编写一个类,用一个成员变量实现统计实例对象个数。

源码

*===============================================
    *   文件名称:work1.cpp
    *   创 建 者:青木莲华
    *   创建日期:2025年08月27日
    *   描    述:使用static成员变量,统计实例对象个数
    ================================================*/
    #include <iostream>
    using namespace std;

class A
{
    public:
    A()
    {
        this->obj_count++;
        cout << "new Object" << endl;
        out_count();
    }
    ~A()
    {
        this->obj_count--;
        cout << "delete Object" << endl;
        out_count();
    }
    void out_count()
    {
        cout << "count = " << this->obj_count << endl;
    }
    private:
    static int obj_count;

};
//初始化 静态变量
int A::obj_count = 0;

int main()
{
    A a;
    A b;
    A c;
    A d;
}

运行截图

alt