类的6个默认成员函数:

类的6个默认成员函数:

构造函数

构造函数:主要完成初始化。是一个特殊的成员函数,名字和类名相同,创建类类型对象时由编译器自动调用,保证每个数据成员都有一个合适的初始值,并且在对象的生命周期内只调用一次。
构造函数的主要任务并不是开辟空间创建对象,而是初始化对象。

特征:
1.函数名与类名相同
2.无返回值
3.对象实例化时编译器自动调用对应的构造函数
4.构造函数可以重载
5.如果类中没有显示定义构造函数,则C++编译器就会自动生成一个无参的默认构造函数,一旦用户显示定义编译器将不再生成。如果用户定义了含有参数的构造函数,却定义了没有参数的类对象,此时编译器不会再生成一个默认的构造函数,抛出没有合适的默认构造函数可用。

无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。注意:无参
构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为是默认成员函数。

1.基本类型(内置类型):int/char...
2.自定义类型:class/struct定义的类型...
默认生成的构造函数,对1不做处理,对2调用无参默认构造函数
析构函数
析构函数:与构造函数功能相反,析构函数不是完成对象的销毁,局部变量(在栈上)销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数,完成类的一些资源清理工作(比如在堆上动态开辟的资源)。

特性:
1.析构函数名是在类名前加上字符~
2.无参数无返回值
3.一个类有且只有一个析构函数。若未显示定义,系统会自动生成默认的析构函数
4.对象生命周期结束时,C++编译系统自动调用析构函数

析构函数调用的时候,是按反着的顺序析构的。比如先构造了类对象d1,d2,d3。析构的时候先析构d3,再析构d2,最后析构d1。因为对象是在函数的栈帧上的,要符合后进先出。
析构函数对内置类型(基本类型)不做什么事情,但是对自定义类型还是会调用自定义类型的析构函数。

拷贝构造函数

拷贝构造函数:只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰,用来保护,不能发生改变),在用已存在的类类型对象创建新对象时由编译器自动调用。

Date d1;
Date d2 = d1;//这个也是拷贝构造函数

特征:
1.拷贝构造函数是构造函数的一个重载形式
2.拷贝构造函数的参数只有一个且必须使用引用传参,使用传值方式会引发无穷递归调用
3.若未显示定义,系统默认的拷贝构造函数。默认的拷贝构造函数对象按内存存储按字节序完成拷贝,这种拷贝叫浅拷贝,或者值拷贝

面试题:
拷贝构造为什么有时候不使用默认的拷贝构造函数?
如果在顺序表中使用浅拷贝,析构函数有free指针,先拷贝构造一个类对象,在free的时候,会把这个指针指向的空间释放俩次,导致程序崩溃。应使用深拷贝。所以不是任何时候都使用浅拷贝,日期这种类就可以用浅拷贝。
将编译器生成的默认拷贝构造函数以及赋值运算符重载称之为浅拷贝方式,即值的拷贝。因此如果一个类中涉及到资源管理,不能使用编译器生成的默认拷贝构造函数以及赋值运算符重载。

运算符重载

运算符重载:返回值类型 operator操作符 (参数列表)
              bool operator==(const Date& d1,const Date& d2)
注意:
1.不能通过连接其他符号来创建新的操作符:比如operator@
2.重载操作符必须有一个类类型或者枚举类型的操作数
3.用于内置类型的操作符,其含义不能改变,例如:内置的整型+ ,不能改变其含义
4.作为类成员的重载函数,其形参看起来比操作数数目少1,成员函数的操作符有一个默认的形参this,限定为第一个形参
5. .* :: sizeof ?: .注意以上5个运算符不能重载。

     d2 =d1;是运算符的重载,把d1的值赋值给d2
data d3 =d1;不是,调用的是拷贝构造函数,拷贝构造一个新对象d3

为了防止自己给自己赋值:
void operator =(const Date& d)
{
	if(this != &d)
	{
          _year = d._year;
        _month = d._month;
        _day = d._day;
	}
}

连续赋值:
Date& operator=(const Date& d)
{
    if(this != &d)
    {
        _year = d._year;
        _month = d._month;
        _day = d._day;
    }
    return *this;
}
d3 = d2 = d1;   //d3 = (d2.operator=(&d2,d1)) 

赋值运算符主要有4点:
1.参数类型
2.返回值
3.检测是否自己给自己赋值
4.返回*this
5.一个类如果没有显示定义赋值运算符重载,编译器也会生成一个,完成对象按字节序的值拷贝
const成员

这里说点题外话

1.用const 修饰函数的参数

如果参数作输出用,不论是传引用传指针,都不能加const,否则该参数失去输出功能。const只能修饰输入参数。

如果参数采用指针传递,加const可以防止意外修改指针,起到保护作用。

如果输入参数采用值传递,由于函数将自动产生临时变量用于复制该参数,该输入参数本来就无需const保护,所以不加const修饰,不管这个参数是内置类型还是自定义类型。

对于自定义类型的参数而言,函数体内将产生自定义类型的临时变量用于复制参数,而临时对象的构造、复制、析构过程都会消耗时间,为了提高效率,可以采用传引用,不需要产生临时变量,为了防止改变参数,所以此时加上const。是否将void Fun(int x)改写成void Fun(const int& x),完全没必要,因为内置类型的参数不存在构造、析构过程,复制很快,传值和传引用效率几乎相同。

总结:对于非内部数据类型的输入参数,应该将“值传递”的方式改为“const 引用传递”,目的是提高效率。例如将voidFunc(A a) 改为void Func(const A &a)。
     对于内部数据类型的输入参数,不要将“值传递”的方式改为“const引用传递”。否则既达不到提高效率的目的,又降低了函数的可理解性。例如void Func(int x) 不应该改为voidFunc(const int &x)。

2.用const修饰函数的返回值

如果给以“指针传递”方式的函数返回值加const修饰,那么函数返回值(即指针)的内容不能被修改,该返回值只能被赋给加const 修饰的同类型指针。例如函数const char *GetString(void);如下语句将出现编译错误:char *str = GetString();正确的用法是const char *str =GetString();如果函数返回值采用“值传递方式”,由于函数会把返回值复制到外部临时的存储单元中,加const修饰没有任何价值。例如不要把函数int GetInt(void) 写成const int GetInt(void)。同理不要把函数AGetA(void) 写成const A GetA(void),其中A 为用户自定义的数据类型。如果返回值不是内部数据类型,将函数AGetA(void) 改写为const A &GetA(void)的确能提高效率。但此时千万千万要小心,一定要搞清楚函数究竟是想返回一个对象的“拷贝”还是仅返回“别名”就可以了,否则程序会出错。函数返回值采用“引用传递”的场合并不多,这种方式一般只出现在类的赋值函数中,目的是为了实现链式表达。d1 = d2 = d3

3.const修饰类的成员函数

将const修饰的类成员函数称之为const成员函数,const修饰类成员函数,实际修饰该成员函数隐含的this指针,this指针指向的内存空间的值不能发生变化,表明在该成员函数中不能对类的任何成员进行修改。

值得注意的是,如果类中存在指针类型的数据成员即便是const,函数只能保证不修改该指针的值,并不能保证不修改指针指向的对象,const对象的成员是不可修改的,然而const对象通过指针维护的对象却是可以修改的。

const成员函数可以被对应的具有相同形参列表的非const成员函数重载

const成员函数不可以修改对象的数据,不管对象是否具有const性质.它在编译时,以是否修改成员数据为依据,进行检查

然而加上mutable修饰符的数据成员,对于任何情况下通过任何手段都可修改,自然此时的const成员函数是可以修改它的
面试题:
1.const对象可以调用非const成员函数吗?
不可以
2.非const对象可以调用const成员函数吗?
可以的,非const对象可以访问任意的成员函数,包括const成员函数。
3.const成员函数内可以调用其它的非const成员函数吗?
不可以。
4.非const成员函数内可以调用其它的const成员函数吗?
可以。
取地址及const取地址操作符重载

这两个默认成员函数一般不用重新定义 ,编译器默认会生成。

Date* operator&()
{
	return this ;
}
const Date* operator&()const
{
	return this ;
}

推荐一篇很不错的文章,对理解const有很大的帮助。

C++ const修饰成员函数:https://blog.csdn.net/zheng19880607/article/details/23883437

发布了19 篇原创文章 · 获赞 18 · 访问量 3641

猜你喜欢

转载自blog.csdn.net/haote216/article/details/88548677