搭建网站用什么语言,云网站制作的流程,WordPress需要什么配置,网站建设经典文章默认成员函数#xff1a;
C环境下每一个类在定义是时编译器会自动生成六个成员函数#xff08;在没有显示定义的情况下#xff09;#xff0c;分别是构造函数、析构函数、拷贝构造函数、赋值运算符重载、普通变量和const常量的取地址重载#xff0c;它们大大弥补了原先C语…默认成员函数
C环境下每一个类在定义是时编译器会自动生成六个成员函数在没有显示定义的情况下分别是构造函数、析构函数、拷贝构造函数、赋值运算符重载、普通变量和const常量的取地址重载它们大大弥补了原先C语言的一些不足为代码编写者提供了极大的遍历下面我们来一一解释各个默认成员函数
构造函数
以栈数据结构为例子C环境下我们在实例化一个栈结构的时候必须手动调用初始化函数但这一步也经常在编写代码的时候忽略本贾尼先生思来想去想出了一个绝妙的方法即在实例化类对象的同时让编译器自动调用一个能够给类属性赋初值的成员函数 为了区分与一般成员函数的与众不同构造函数的形式非常独特它没有返回值但不需要再声明定义处前加上void关键字当不需要传参时调用不需要添加空括号,函数名与类对象名相同。
//栈
class Stack
{
public:Stack(int n4){_a(int*)malloc(sizeof(int)*n);_size0;_capacity0;} //显示定义带有缺省值构造函数
private:int *_a;int _size;int _capacity;
};Stack st1; //不传参调用写括号编译器分不清是调用还是声明
Stack st1(10); //传参调用如果我们显示声明定义了构造函数那么编译器就不会自动生成而是执行我们写的那么如果我们不写的话打印一下三个类属性会出现什么结果呢 答案是一串随机值这里可以说是C的一个缺陷自动生成的构造函数不会对内置类型作出任何处理只对自定义类型调用该类型本身的构造函数举个例子
class Queue
{
public:Queue(){_head_tailnullptr;}
private:int* _head;int * _tail;
};
//定义一个Queue对象 q1 充当Stack的类属性在调试窗口观察四个类属性的值 q的值确实被初始化成了空指针由于编译器版本的原因可能会将内置类型初始化为0但这里我们依然认为不对内置类型做处理
C11在此基础上做了优化在类属性声明处可以直接给缺省值来实现初始化具体例子在讲解拷贝构造时给出
析构函数
C环境下总是要手动调用销毁结构释放空间同样极易被遗忘从而在C环境中衍生出另一个默认成员函数当类对象生命结束时会自动调用析构函数实现空间释放 与构造函数很像析构函数也是没有返回值且不需要前缀void的特殊函数并且它不具有参数不能重载构造函数可以重载 为了区分构造函数析构函数的函数名前有前缀按位取反符 ~
//实现一个栈的析构函数
class Stack{
public://………………~Stack(){free(_a);_anullptr;_size_capacity0;}//………………
};同理如果不显示声明定义编译器会自动生成析构函数并调用
拷贝构造函数
我们有时候会想要创造一个与一个已有类对象的对象这个时候我们就需要拷贝编译器默认的拷贝方式是浅拷贝值拷贝即将被拷贝的值逐个字节的传递给拷贝值这样的方式对于int、char、double这些内置类型是没有问题的但是对于指针类型或者自定义类型是不行的原因是因为如果含有指针类型浅拷贝后会出现两个指针指向同一块空间的情况这样出现两次析构的时候就会报错因此这里需要采用深拷贝的方式C使用了拷贝构造函数来实现。
拷贝构造函数是构造函数的重载没有返回值参数类对象引用这里必须通过引用传参一是能够提升效率二是如果传值调用会出现无限递归的结果导致程序崩溃具体图解在后文会给出
class Date//定义日期类
{
public:Date(const Date d){ //我们不想改变被拷贝值加const是一个好习惯_yeard._year;_monthd._month;_dayd._day;}
private:_year2024;_month1;_day1;//C11的特性
};Date d1;
Date d2(d1);//①
Date d2d1; //② 两种方法是等价的都是初始化时将d1值拷贝给d2解释为何不能传值调用 既定事实自定义类型的拷贝需要使用拷贝构造
运算符重载
C为了增强代码的可读性引入了运算符重载运算符重载是具有特殊函数名的函数也具有其返回值类型函数名字以及参数列表其返回值类型与参数列表与普通的函数类似。
函数名字为关键字operator后面接需要重载的运算符符号 函数原型返回值类型 operator操作符(参数列表)
1、不能通过连接其他符号来创建新的操作符比如operator 2、重载操作符必须有一个类类型或者枚举类型的操作数 3、用于内置类型的操作符其含义不能改变例如内置的整型不 能改变其含义 4、作为类成员的重载函数时其形参看起来比操作数数目少1成员函数的操作符有一个默认的形参this限定为第一个形参 5、**. 、:: 、sizeof 、?: 、.** 注意以上5个运算符不能重载*
以对运算符的重载为例(Date类)
class Date//定义日期类
{
public:Date operator(int year) {_yearyear;return *this;//思考一下为什么传引用返回}
private:_year2024;_month1;_day1;//C11的特性
};Date d1;
d11;//隐式调用
d1.operator(1);//显示调用
赋值运算符重载 赋值运算符作为默认成员函数之一对于类属性只有内置类型的对象可以不需要我们手动编写编译器会自动生成并调用。
取地址重载
class Date
{
public :Date* operator(){return this ;}const Date* operator(){return this ;}
private :int _year ; int _month ; int _day ;
};这两个运算符一般不需要重载使用编译器生成的默认取地址的重载即可故不做过多阐述。
……………………………………………………………………………………………………