首言
这是我对于在学习类与对象时的一些思考与总结。主要去讲解C++自主实现的默认构造函数。
1. 6大默认成员函数
1.1 是什么
默认的成员函数,是由c++ 编译器自动生成的。我们即使不定义,也可以调用。有默认构造函数、默认拷贝构造函数、默认析构函数、赋值重载、对于不同对象与const对象取地址重载(最后这个不常见)。
2 构造函数
1.2.1 是什么
构造函数,是对于类的对象进行赋值的一个函数(注意这里不是进行初始化!初始化的话需要使用初始化列表,详细内容我将会在下中详细讲解)。它的特点是:类名就是他的函数名。他的代码使用如下所示:(以Date类进行举例)
//这种定义方式有很大的缺陷
Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
大家请看这两张图片:可以发现,当我们重新定义了构造函数的时候,我们就只能定义成第一张图的样子,当定义为空(或者其他)的时候就会出错。所以很不建议使用这种方法来进行定义。
最推荐的方法如下:使用全缺省的方法来进行实现:
Date(int year = 1997, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
1.2.2 注意细节
特点:1.没有返回值。2.对象实例化时编译器自动调用对应的构造函数。3.可以进行重载。
还有一点默认的构造函数仅仅只会对自定义类型的成员函数进行调用,对于内置类型的成员函数不会调用构造函数,依旧是随机值。
常见的默认构造函数有三个:1.我们不写编译器自动生成的。
2.全缺省的也是我最推荐的。
3.无参数的构造函数。
3 析构函数
3.1 是什么
对象在销毁时会自动调用析构函数,完成对象中资源的清理工作。。书写是 ~ + 类名 。
具有三个特征:1.函数没有返回值 2.析构函数不能重载。
~Date()
{}
需要特别注意的是,内置成员变量(int ,char,...),销毁时不需要资源的清理,最后系统直接将其内存回收了即可。但是对于自定义类型的成员变量,在销毁的时候需要调用他的析构函数。通过下面的代码,即可了解。
class Time
{
public:
~Time()
{
cout << "This is ~Time()" << endl;
}
private:
int _hour;
int _month;
int _s;
};
class Date
{
public:
private:
int _day;
int _month;
int _year;
Time t;
};
4 拷贝构造函数
4.1 是什么
拷贝构造函数:只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用。相当于复制一个一模一样的自己。最重要的工作是完成对象的拷贝。
特征:1. 相当于是对于构造函数的一个重载功能。
2.传递的参数,只有一个并且是对于对象的引用传递,如果使用类进行传递会引发无穷递归。
Date(const Date &d1)
{
_year = d1._year;
_month = d1._month;
_day = d1._day;
}
3.其次比较重要的一点是:拷贝构造函数是进行初始化,适用于没有创建好的类对象。需要跟赋值运算符的重载区分开。
4.2 赋值运算符的重载
关于赋值运算符,它只能定义为成员函数存放在类里面,不能够放在在外面。这样的话会造成主要的main 函数与重载的 = 相互冲突。
//实现赋值运算符的重载
Date& operator=(const Date& d)
{
_day = d._day;
_month = d._month;
_year = d._year;
}
4.3 深、浅拷贝
当我们将赋值运算符重载,拷贝构造给删除掉。我们依然可以使用拷贝跟运算符的重载。这里就是按照字节来进行的值拷贝,将其称之为:浅拷贝。
而深拷贝就是我们进行对赋值运算符的重载,以及对于拷贝构造函数的重载。
我们不用定义的话,也可以实现一些值拷贝,那我们为什么还要进行深拷贝呢?我们在 date 日期来可能不明显,但是当我们对 Stack 栈,进行拷贝的时候就会出现许多的问题。当按照字节进行拷贝,会使他指向同一块空间的进行删除的操作,会对同一块空间重复的删除,引发大量的问题。
对于后面的两个默认的成员函数,就不再进行详细的讨论。
5 其他运算符的重载
5.1 前置与后置++的重载。
Date& operator++()//前置++
{
_day++;
return *this;
}
Date operator++(int)//后置++
{
Date cur = *this;
_day++;
return cur;
}
1.5.2 -- 的重载
Date& operator--()
{
_day--;
return *this;
}
Date operator--(int)
{
Date tmp = *this;
_day--;
return tmp;
}
关于这里面的为什么去使用 Date&,有的是去使用Date。是因为前置的++,返回已经改变的值使用引用,可以提高效率。对于后置的++需要返回之前的值,如果是使用引用的话,这个出了作用域就不存在了。所以应当去使用Date来作为返回值。
2. const成员
const 去修饰的函数称之为 const成员函数。实际上对于类来说是去修饰的的 *this指针,表示里面不能对 *this 所指向的内容进行修改。
接下来思考几个问题:
1. const对象可以调用非const成员函数吗?
2. 非const对象可以调用const成员函数吗?
3. const成员函数内可以调用其它的非const成员函数吗?
4. 非const成员函数内可以调用其它的const成员函数吗?
1.不可以,因为有const修饰的对象是可写的,但是非cosnt成员函数是可读可写的。扩大了范围。
2.可以 3.不可以,一样的扩大了范围 4.可以
结尾
在这里只是进行一些简单的解释,想要更加深入的了解的话需要实现Date日期类。如果对你有帮助还请帮我点个免费的赞,支持一下我,我也会不断地改进争取写出跟高质量的文章。我们共同努力!!!!