文章目录
C++ 类的6个默认成员函数
每创建一个类,编译器会自动生成6个默认的成员函数
1构造函数
构造函数的主要任务不是开空间创建对象,而是初始化对象。
- 函数名与类名相同
- 无返回值
- 对象实例化时编译器自动调用对应的构造函数
- 构造函数可以重载
注:
- 调用无参构造函数时不用加“()”避免与函数声明二义性
- 构造函数初始化尽量使用初始化列表,即A():a(1),b(2){}的方式对成员变量,避免与与函数缺省冲突。
- 用户未定义构造函数编译器自动生成 用户显式(手动)定义编译器不再生成
class A
{
public:
A( )
{
};
A(int a )
{
_a = a;
}
private:
int _a;
};
int main()
{
A a;
A a(1);
return 0;
}
2析构函数
对象的生命周期到了,编译器自动调用析构函数
- 没有显式定义析构函数,编译器会自动生成
- 命名类似构造函数,在类名前加~符号
- 用调试会发现会在return处调用
- 先创建的对象会压栈,当函数运行完编译器会在return处进行收尾工作先创建的对象最后调用析构函数。
#include <iostream>
using namespace std;
class A
{
public:
A( )
{
};
A(int a )
{
_a = a;
}
~A()
{
_a = 0;
}
private:
int _a;
};
int main()
{
A a;
A a(1);
return 0;
}
2拷贝构造函数(简称拷贝构造)
先看下面一段代码;
int main()
{
A a(1);
A b(a);
return 0;
}
这里调用的就是a的拷贝构造,类似于构造函数,但是构造函数主要进行赋值操作,拷贝则是将一个类拷贝到另外一个类中
下面看A的定义
class A
{
public:
A( )
{
_a = 0;
};
A(int a )
{
_a = a;
}
~A()
{
_a = 0;
}
private:
int _a;
};
这里会发现 并没有对A(A *a)类型的重载这是因为编译器由自动生成了A的拷贝构造,
但是编译器自动生成的拷贝构造有很大的问题
编译器自动生成会把a的每个字节都拷贝到b中 (浅拷贝)
但如果类中有指针同样会把地址的值赋过去,而不是重新开辟空间
因此显式定义一个拷贝构造很是关键
拷贝构造写法
- 名称为类名
- 参数必须用引用,不然形参与实参的传递会导致无限调用拷贝构造。
class A
{
public:
A( )//无参数构造函数
{
_a = 0;
};
A(int a )//单参数构造函数
{
_a = a;
}
A(const A& a)//拷贝构造
{
_a = a._a;
}
~A()//析构函数
{
_a = 0;
}
private:
int _a;
};
4赋值运算赋的重载
先看下面一段代码
int main()
{
A a(1);
A b=a;//等号两边是A类型
return 0;
}
那么编译器是怎么去实现的呢
这里编译器又背着我们干了一件事情,生成了一个赋值运算符重载,也是按字节进行拷贝
如何自己去写
关键字 operator
class A
{
public:
A( )//无参数构造函数
{
_a = 0;
};
A(int a )//单参数构造函数
{
_a = a;
}
A(const A& a)//拷贝构造
{
_a = a._a;
}
~A()//析构函数
{
_a = 0;
}
A& operator =(const A &b)
{
(*this)._a = b._a;
return *this;
}
private:
int _a;
};
- 不能通过连接其他符号来创建新的操作符
- 重载操作符必须有一个类类型或者枚举类型的操作数
- 用于内置类型的操作符,其含义不能改变,例如:内置的整型+,不 能改变其含义
- 作为类成员的重载函数时,其形参看起来比操作数数目少1成员函数的操作符有一个默认的形参this,限定为第一个形参
- “.*” 、"::" 、“sizeof” 、"?:"、"." 注意以上5个运算符不能重载。这个经常在笔试选择题中出现。
5&&6 取地址及const取地址
class A
{
public:
A(int a =0)//单参数与无参数构造函数
{
_a = a;
}
A(const A& a)//拷贝构造
{
_a = a._a;
}
~A()//析构函数
{
_a = 0;
}
A& operator =(const A &b)//赋值运算符重载
{
(*this)._a = b._a;
return *this;
}
A* operator&()//&重载
{
return this;
}
const A* operator&()const //const对象&重载
{
return this;
}
private:
int _a;
};
编译器会自动生成,一般很少需要对其进行重载。