声明:危险等级:1级,2级,3级,4级
1.C++中声明和定义的区别
首先,我们拿出一串代码,以这串代码为例,来讨论声明与定义的区别。
在C语言中,声明是没有给变量开空间,定义是对变量初始化,开空间。C++也是如此。
class date//定义日期类
{
public://访问限定符是语法层面的东西
void init(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
private://声明
int _year;
int _month;
int _day;
};
根据C++的写法,在访问限定符里面写出来的成员变量,是声明。
注意:因为这里没有给到这些成员变量开空间,即没有初始化,所以属于声明语句。
那么,接下来我们就要了解到什么是定义了。
定义在这里解释就是实例化对象:Date d1 当我们实例化出对象d1,就相当于我们构造出了d1对象,d1对象不仅定义成员变量,通俗点说构造出了成员变量,这样就是定义了成员变量。
int main()
{
Date d1;//对象的实例化会实例化出对象,这样就定义了成员变量
return 0;
}
2.简单日期类代码发现细节问题
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(2024, 5, 20);
d1.Print();
return 0;
}
这串代码的含义就是输出日期2024-5-20,这里d1.Init(2024,5,20),如果感觉不太好理解这串代码的意思,可以类比结构体变量访问结构体成员,这里是类对象访问类成员函数,然后调用Print函数得到日期。
3.this指针
以上问题都很好理解,但是到了this指针这块便是一个个比较难啃的瓜,是个重难点。
1.this指针的引入
我有一个问题:如果我实例化两个对象,然后Init参数不一样,这样调用的函数是同一个吗?看一下代码:
int main()
{
Date d1;
Date d2;
d1.Init(2024, 5, 20);
d2.Init(1,2,3);
d1.Print();
d2.Print();
return 0;
}
我们在vs环境下尝试看看汇编代码Init函数调用时的地址:
不难看出,地址都是一样的,所以调用的函数都是一样的。那么为什么调用同一个函数,但是结果(日期)却不一样呢?那我们赶紧把重头戏端出来看一看。
2.this指针
我们先直接上一串关于编译器没有优化或者说是自行处理的代码与现代码进行对比:
#include<iostream>
using namespace std;
class Date
{
public:
//void Init(const Date&this, int year, int month, int day)
void Init(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
//void Print(const Date&this)
/*{
cout << this->_year << "-" <<this-> _month << "-" << this->_day << endl;
}*/
void Print()
{
cout << _year << "-" << _month << "-" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1;
Date d2;
//d1.Init(&d1,2024,5,20);
d1.Init(2024, 5, 20);
d2.Init(1, 1, 1);
//d1.Print(&d1);
d1.Print();
//d2.Print(&d2);
d2.Print();
return 0;
}
我所注释掉的就是编译器自己执行的代码。根据编译器的处理,this指针存放的是调用的类对象的地址,这样的话就不难发现为何虽然函数一样但是结果不同的原因了。
3.默认成员函数
1.构造函数
只要记住,构造函数相当于之前写的Init函数。
用法:1.函数名与类名相同
2.无返回值
3.自动调用
#include<iostream>
using namespace std;
class Date
{
public:
Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
cout << "Date()" << endl;
}
/*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(2024,5,20);
d1.Print();
return 0;
}
如上图代码所示,这是调用的结果:
看运行结果就知道编译器自己调用了构造函数。所以说,以后Init就退出历史舞台了。(蓝瘦香菇)。
值得注意的是:这里初始化的写法:Date d1(2024,5,20),这是专门与构造函数配对的写法。
2.析构函数
析构函数
自动销毁的函数
1.命名时跟构造函数一样,但是类名前加入“~”
2.无参数无返回值类型
3.一个类只能有一个析构函数
4.对象生命周期结束,自动调用该函数
~Date()
{
_year=0;
_month=0;
_day=0;
}
一般来说,析构函数是用来释放malloc等内存函数开辟的空间,这里是为了方便演示,选择free掉日期类。