目录

1.构造函数

(1)引入

(2)性质与验证

(3)总结

2.析构函数

(1)概念

(2)性质与验证

(3)总结

3拷贝构造函数

(1)概念

(2)性质与验证

(3)总结

4.赋值运算符重载

(1)概念

(2)性质与验证

(3)赋值运算符重载

(4)单目运算符重载

(5)总结

5.普通对象取地址操作符重载

6.const对象取地址操作符重载


C++类中共有6个默认成员函数,分别是构造函数、析构函数、拷贝构造函数、赋值运算符重载、普通对象取地址及const对象取地址操作符重载。主要功能如下图所示:

1.构造函数

(1)引入

想要知道什么是构造函数,先来看一个简单的例子。一般情况下,使用内置类型定义变量并赋值时是这样的:int a = 10,但还有一种方法是:int a(10)。如同代码一:

代码一:int a(10) 这样的定义方式。(本文代码均在win10系统下的vs2019验证)

//代码一
#include "iostream"
using namespace std;int main() {int a(10);cout <<"a = " << a << endl;//输出 a = 10
}

构造函数就是想让类类型也可以这样定义变量并赋值。

(2)性质与验证

<1>构造函数名与类名相同,且无返回值。

代码二:

//代码二
#include "iostream"
using namespace std;class Date {
private:int _year;int _month;int _day;
public:Date(int year, int month, int day) {_year = year;_month = month;_day = day;}
};int main() {Date d1(2012, 12, 12);
}

<2>创建类类型的对象时,由编译器自动调用。

通过观察代码二的汇编指令验证。如下图所示,将汇编指令处理后可以看到,编译器自动call了构造函数。(call指令代表着函数调用,call指令上面那几行代表参数压栈)

<3>构造函数可以重载。

        代码三:

//代码三
#include "iostream"
using namespace std;class Date {
private:int _year;int _month;int _day;
public:Date(int year, int month, int day) {_year = year;_month = month;_day = day;cout << _year <<"-" << _month << "-" << _day << endl;}Date(int year, int month) {_year = year;_month = month;cout << _year << "-" << _month << endl;}
};int main() {Date d1(2012, 12, 12);//输出 2012-12-12Date d2(1990, 10);//输出 1990-10
}

<4>如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,否则编译器不会自动生成。如果还需要使用默认构造函数,需要用户自己添加一个无参构造函数。

        代码四:

//代码四
#include "iostream"
using namespace std;class Date {
private:int _year;int _month;int _day;
public:Date(int year, int month, int day) {_year = year;_month = month;_day = day;cout << _year <<"-" << _month << "-" << _day << endl;}
};int main() {Date d1(2012, 12, 12);Date d2;//报错
}

<5>构造函数在对象的生命周期内只调用一次。

        代码五:通过在构造函数中添加打印语句可以验证。该语句只会打印一次。

//代码五
#include "iostream"
using namespace std;class Date {
private:int _year;int _month;int _day;
public:Date(int year, int month, int day) {_year = year;_month = month;_day = day;cout << "构造函数被调用";}
};int main() {Date d1(2012, 12, 12);//输出 构造函数被调用
}

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

代码六:当无参构造函数和全缺省构造函数都被显式定义,将会报错。

//代码六
#include "iostream"
using namespace std;class Date {
private:int _year;int _month;int _day;
public:Date(int year = 2020, int month = 12, int day = 20) {_year = year;_month = month;_day = day;cout << "全缺省构造函数被调用";}Date() {cout << "无参构造函数被调用";}
};int main() {Date d1;//报错
}

<7>疑问:如果不实现构造函数,编译器会生成默认的构造函数,但默认构造函数生成的成员变量是随机值,貌似默认构造函数没啥用?其实是有用的。(验证比较长,请耐心看完)

代码七:此代码有两个类,Date类和Time类,其中Date类中有Time类的对象t1,且Date类中没有显式定义构造函数。

如果要创建Date类的对象,自然需要初始化它的成员变量。t1作为Date类的成员变量,要想将t1初始化就必须调用Time的构造函数。

那么怎么调用Time的构造函数呢,直接调用是不可以的。原因:创建A类的对象,就只能调用A类的构造函数。所以,想要调用Time的构造函数,就必须在Date类的构造函数中调用Time类的构造函数。但是Date类中没有显式定义构造函数,这时候默认的构造函数就发挥作用了。所以,默认构造函数是有用的。

//代码七
#include "iostream"
using namespace std;class Time {
private:int _hour;int _minute;int _second;
public:Time() {cout << "Time构造函数被调用" << endl;}
};class Date {
private:int _year;int _month;int _day;Time t1;
};int main() {Date d1;//输出 Time构造函数被调用
}

(3)总结

构造函数特征:

<1>函数名和类名相同。

<2>无返回值。

<3>对象实例化时编译器自动调用对应的构造函数。

<4>构造函数可以重载。

<5>构造函数在对象的生命周期内只调用一次。

<6>如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,否则编译器不会自动生成。如果还需要使用默认构造函数,需要用户自己添加一个无参构造函数。

<7>无参的构造函数和全缺省的构造函数都被称为默认构造函数,并且默认构造函数有一个。

<8>构造函数虽然名称叫构造,但是需要注意构造函数的主要任务并不是开辟空间创建对象,而是初始化对象。

2.析构函数

(1)概念

析构函数:与构造函数功能相反,析构函数不是完成对象的销毁,局部对象销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数,完成类的一些资源清理工作。

        析构函数也是默认成员函数之一,但我们有时仍然需要手动实现,因为编译器提供的默认析构函数并不能处理所有情况,可能会造成内存泄露

验证内存泄漏,代码八:使用VS2019内置函数 _CrtDumpMemoryLeaks() 来检测内存泄漏,可以在输出窗口中查看检测结果。

//代码八
#include "iostream"
#include "malloc.h"
using namespace std;class Test {
public:int* arr;
public:Test() {arr = (int*)malloc(10);}~Test() {if (arr) {free(arr);arr = nullptr;}}
};void T() {Test t1;
}int main() {T();_CrtDumpMemoryLeaks();return 0;
}

上述代码的输出信息:输出窗口的检测结果显示有10个字节的的内存泄露。说明内置的析构函数无法处理动态申请的空间,需要用户显式定义合适的析构函数。

析构函数语法:~类名(){} 用户需要在函数体中添加合适的释放资源的方式,以避免内存泄漏。

(2)性质与验证

<1>析构函数名是在类名前加~。

<2>析构函数无参数,无返回值。

<3>一个类有且只有一个析构函数 (也就是说析构函数不能重载)。若未显式定义,系统会自动生成默认的析构函数。(但实际上并不一定会生成,因为需要考虑效率等)

        代码九:此代码恰好与代码七是相反的,因为一个是验证构造函数,一个是验证析构函数。

此代码有两个类,Date类和Time类,其中Date类中有Time类的对象t1,且Date类没有显示定义析构函数。

要销毁Date类的对象,自然需要销毁它的成员变量。t1作为Date类的成员变量,要想将t1销毁就必须调用Time的构造函数。

如何调用Time的析构函数呢?直接调用是不可以的。原因:销毁A类的对象,就只能调用A类的析构函数。所以,想要调用Time的析构函数,就必须在Date类的析构函数中调用Time类的析构函数。但是Date类中没有显式定义析构函数,此时编译器将会为Date类生成默认的析构函数。这一点通过代码九的汇编来体现。

//代码九
#include "iostream"
using namespace std;class Time {
private:int _hour;int _minute;int _second;
public:Time() {cout << "Time构造函数被调用" << endl;}~Time() {cout << "Time析构函数被调用" << endl;}
};class Date {
private:int _year;int _month;int _day;Time t1;
};int main() {Date d1;
}

代码九中Test()函数对应的汇编如下:可以看到,在Test()函数结束后,t1对象的生命周期结束,系统自动调用了默认的构造函数。

<4>对象生命周期结束时,C++编译系统自动调用析构函数。

        注:各类对象生命周期

1.全局对象---程序退出时销毁

2.函数体内部的局部对象---函数退出时 或者 出了该函数的作用域

3.函数体内部的static修饰的局部对象---程序退出时被销毁

4.堆上创建的对象---程序员控制

        代码十:通过观察以下代码的汇编指令来理解。

//代码十
#include "iostream"
#include "malloc.h"
using namespace std;class Test {
public:int* arr;
public:Test() {arr = (int*)malloc(10);}~Test() {if (arr) {free(arr);arr = nullptr;}}
};void T() {Test t1;
}int main() {T();_CrtDumpMemoryLeaks();return 0;
}

以下是代码十的汇编指令,处理掉多余部分:可以看到,在函数体中调用了对象的构造方法,函数结束后,对象的生命周期也结束了,系统自动调用析构函数。

(3)总结

析构函数特征:

<1>析构函数名是在类名前加上字符~。

<2>析构函数没有参数和返回值。

<3>一个类只有一个析构函数,若未显式定义,系统会自动生成默认的析构函数。

<4>对象生命周期结束时,C++编译系统自动调用析构函数。

3拷贝构造函数

(1)概念

概念:只有单个形参,该形参是本类类型对象的引用(一般用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用。

为什么需要拷贝构造函数?在内置类型中,可以用一个变量给另一个变量赋值,如代码十一。

代码十一:

//代码十一
#include "iostream"
using namespace std;int main() {int a = 10;int b = a;int c(a);cout << "b=" << b << endl;//输出 b=10cout << "c=" << c << endl;//输出 c=10
}

但现在我们定义的类类型的变量(也就是对象),也想拥有这样的赋值方式。这就需要用到拷贝构造函数来实现。

(2)性质与验证

<1>拷贝构造函数时构造函数的一个重载函数。(所以拷贝构造函数的函数名也是类名)

<2>拷贝构造函数的参数只有一个且必须使用引用传参,使用传值方式会引发无穷递归调用。(建议将参数设置为 const 类名* 引用变量,避免手误将引用变量修改)

        代码十二:此代码举例拷贝构造函数的用法:

//代码十二
#include "iostream"
using namespace std;class Date {
private:int _year;int _month;int _day;
public:Date(int year,int month,int day) {_year = year;_month = month;_day = day;}Date(const Date& d) {_year = d._year;_month =d._month;_day = d._day;}void Print() {cout << _year <<"-" << _month <<"-" << _day << endl;}
};int main() {Date d1(2020,12,12);Date d2(d1);Date d3 = d1;d1.Print();//输出 2020-12-12d2.Print();//输出 2020-12-12d3.Print();//输出 2020-12-12
}

下面这幅图验证传值方式会引发无穷递归调用。

        如下图:如果参数是传值方式,如果要用d1拷贝构造d2,传参的时候就需要发生值拷贝,拷贝一份和d1一样的dCopy用来当作参数,既然需要拷贝一份dCopy,那自然又需要调用拷贝构造,调用之后又需要进行值拷贝……这样下来,将会无限递归下去。

<3>若未显式定义,系统生成默认的拷贝构造函数。默认的拷贝构造函数对象按内存存储,按字节拷贝,这种拷贝叫做浅拷贝,或者值拷贝。(定义有些不好理解,可以这么说,默认拷贝构造函数会将对象中所有东西一摸一样的拷贝给另一个对象)

浅拷贝:多个对象共用同一份资源,当这些对象销毁时,资源会被释放多次而引起程序崩溃。

当涉及到资源管理的时候,这种浅拷贝方式很危险。如代码十三。

代码十三:

//代码十三
#include "iostream"
#include "malloc.h"
using namespace std;class Test {
public:int* arr;
public:Test() {arr = (int*)malloc(10);}
};int main() {Test t1;Test t2 = t1;cout <<"t1中arr指向的空间地址:" << t1.arr << endl;cout <<"t2中arr指向的空间地址:" << t2.arr << endl;return 0;
}

下图是打印结果:可以看到两个对象的arr指针指向的空间是相同的。

arr是对象中的一个指针,保存了一个空间的地址,但是由于浅拷贝,所以两个对象中的arr保存的地址相同,导致两个arr指向了同一块空间。

貌似到这里没有发生什么问题,可是一旦其中一个对象销毁,将它内部的arr指向的空间释放掉,那么另一个对象中的arr会怎么样?另一个对象中的arr会指向一块被销毁的空间,arr也就成了野指针,如果该对象再次访问arr所指向的空间时,毫无疑问程序会出错,这就是默认析构函数的浅拷贝危害。

<4>用匿名对象做返回值。

代码十四:如同代码十四中 Tes2() 函数的返回形式叫做匿名对象,返回值没有对象名。

//代码十四
#include "iostream"
using namespace std;class Test {
public:int _a;
public:Test(int a) {_a = a;cout << "构造函数调用" << endl;}Test(const Test& t) {_a = t._a;cout << "拷贝构造函数调用" << endl;}
};
Test Tes1() {Test t (20);return t;
}Test Tes2() {return Test(30);
}
int main() {cout << "这是Tes1函数打印结果:" << endl << endl;Test t1 = Tes1();cout<< "=================" << endl;cout << "这是Tes2函数打印结果" << endl << endl;;Test t2 = Tes2();return 0;
}

下图是代码十四的打印结果:可以看到使用匿名对象做返回值,系统将不会调用拷贝构造函数构造临时对象返回,效率要更高,所以推荐使用匿名对象返回。

(3)总结

        <1>拷贝构造函数时构造函数的一个重载函数。

        <2>拷贝构造函数的参数只有一个且必须使用引用传参,使用传值方式会引发无穷递归调用。

        <3>若未显式定义,系统生成默认的拷贝构造函数。(注意:默认构造函数是浅拷贝)

4.赋值运算符重载

(1)概念

运算符重载:C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值与参数列表和普通的函数相似。

为什么要重载运算符?内置类型比如int类型的变量,可以进行判断是否相等,比较大小等操作,而自定义的类类型的对象也想实现这些操作,但内置的 > < == 等符号显然不能满足要求,那么我们可以写特定的函数来实现这些功能,但是普通的函数需要通过函数名调用,看起来不直观,所以引入了运算符重载。

举例:如同代码十五中的比较方法,使用较为繁琐,不直观。

代码十五:

//代码十五
#include "iostream"
using namespace std;class Test {
public:int _a;
public:Test(int a) {_a = a;}bool Comper(const Test& t) {return _a > t._a;}
};
int main() {Test t1(12);Test t2(90);if (t1.Comper(t2)) {cout << "t1大" << endl;}else{cout << "t2大" << endl;}
}

(2)性质与验证

<1>函数名:operator 需要重载的符号 。operator是重载运算符的关键字。

<2>函数原型:返回值类型 operator 操作符(参数列表)。

代码十六:将代码十五修改。可以看到,它有两种调用方式,一种是通过函数名调用,另一种是运算符两侧加上操作数调用。毫无疑问,第二种更直观,更简洁。

//代码十六
#include "iostream"
using namespace std;class Test {
public:int _a;
public:Test(int a) {_a = a;}};bool operator==(const Test& t1, const Test& t2) {return t1._a == t2._a;
}int main() {Test t1(12);Test t2(90);if (operator==(t1, t2))cout << "相等" << endl;elsecout << "不相等" << endl;if (t1 == t2)cout << "相等" << endl;elsecout << "不相等" << endl;
}

<3>不能通过连接其他符号来创建新的操作符:比如operator@,C++中没有@这个操作符,所以重载没用。

<4>重载操作符必须有一个类类型或者枚举类型的操作数。

代码十七:两个参数均是内置类型,这样会报错。因为内置类型本来就可以直接用操作符操作,不需要重载操作符。所以才规定操作数必须有至少有一个是自定义类型。

//代码十七
#include "iostream"
using namespace std;bool operator==(int a, int b) {
}int main() {
}

<5>用于内置类型的操作符,其含义不能改变,例如:内置的+,不能改变其含义。

这个的意思是,如果重载了+这个符号,就不能在函数体里面实现的却是 - 的操作。这样的话,虽然不会报错,但是会让人使用起来不方便、不习惯。

<6>作为类成员的重载函数时,其形参看起来比操作数的数目少1。成员函数的操作符有一个默认的形参this,限定为第一个形参。

代码十七:如果将运算符重载函数定义在类内部,就必须在原有的参数个数基础上减1,因为类的成员函数的参数列表中会有隐含的this指针。如果不减1,参数的个数就和该运算符能操作的运算数不匹配,就会报错。

比如: == 的左右两边各一个操作数,如果不减1,加上this指针就是三个操作数,一个 == 怎么同时对三个数进行操作?

//代码十七
#include "iostream"
using namespace std;class Test {
public:int _a;
public:Test(int a) {_a = a;}bool operator==(const Test& t) {return _a == t._a;}
};int main() {Test t1(12);Test t2(90);if (t1.operator==(t2))cout << "相等" << endl;elsecout << "不相等" << endl;if (t1 == t2)cout << "相等" << endl;elsecout << "不相等" << endl;
}

<7> (.*) (::) (sizeof) (?:) (.)以上五个运算符不可以重载。

(3)赋值运算符重载

赋值运算符重载必须重载成类的成员函数。否则报错。

        原因:赋值运算符是类中默认的成员函数,如果用户没有在类中显式实现,则编译器会自动生成一份。如果自己在类外再写一份,就相当于有两份赋值运算符重载函数,相当于重定义。

        赋值运算符较为特殊,重载时需要注意,赋值运算符是可以连续赋值的,如:a = b = 1。连续赋值的机制是,先用11给b赋值,然后用b给a赋值,可以通过这条指令的汇编得出。

对于这些常用的汇编指令在我的往期博客《引用和指针的区别与联系》中有过讲解,不了解的可以看一下。

了解了内置类型连续赋值的机制,重载赋值运算符自然也要实现这样的机制。

代码十八:每个赋值运算符都是一次函数调用,要实现连续赋值,自然需要多次调用函数,那么为它设置一个返回值,让它用返回值去继续向前赋值即可。

第一种调用方式比较好理解,t1赋值给t2,将t2对象返回,然后将这个返回值作为参数传递给t3调用的赋值函数。

第二种方式是经过简化的,也是最直观的。

注意:这里返回值类型是类类型的引用,这样不必进行值拷贝,效率高。

//代码十八
#include "iostream"
using namespace std;class Test {
public:int _a;
public:Test(int a) {_a = a;}Test& operator=(const Test& t) {_a = t._a;return *this;}
};int main() {Test t1(12);Test t2(0);Test t3(0);//想实现 t3 = t2 = t1t3.operator=(t2.operator=(t1));cout << t1._a << " " << t2._a << " " << t3._a << endl;//输出 12 12 12t3 = t2 = t1;cout << t1._a << " " << t2._a << " " << t3._a << endl;//输出 12 12 12
}

(4)单目运算符重载

举例:前置++、后置++、前置--、后置--。这些操作符只需要一个操作数,然后将运算完的数据返回。

<1>前置++

代码十九:

//代码十九
#include "iostream"
using namespace std;class Test {
public:int _a;
public:Test(int a) {_a = a;}//前置++Test& operator++() {_a += 1;return *this;}
};int main() {Test t1(0);++t1;cout << t1._a << endl;//输出 1
}

<2>后置++

后置++特殊,因为需要和前置++区分,语法规定:在重载后置++时,可以多增加一个int类型的参数。(必须这样做)

代码二十:重载后置++时,应该先拷贝一份this指针指向的对象,然后进行后置++,将之前保存的对象返回。

//代码二十
#include "iostream"
using namespace std;class Test {
public:int _a;
public:Test(int a) {_a = a;}//后置++Test& operator++(int a) {Test temp(*this);_a += 1;return temp;}
};int main() {Test t1(0);t1++;cout << t1._a << endl;//输出 1
}

(5)总结

<1>函数名:operator 需要重载的符号 。operator是重载运算符的关键字。

<2>函数原型:返回值类型 operator 操作符(参数列表)。

<3>不能通过连接其他符号来创建新的操作符:比如operator@

<4>重载操作符必须有一个类类型或者枚举类型的操作数。

<5>用于内置类型的操作符,其含义不能改变,例如:内置的+,不能改变其含义。

<6>作为类成员的重载函数时,其形参看起来比操作数的数目少1。成员函数的操作符有一个默认的形参this,限定为第一个形参。

<7> (.*) (::) (sizeof) (?:) (.)以上五个运算符不可以重载。

5.普通对象取地址操作符重载

如果想要在取地址的时候,进行别的操作(比如打印地址),可以将取地址操作符重载。

代码二十一:注意,取地址操作符的函数返回值类型是:本类型的指针。

//代码二十一
#include "iostream"
using namespace std;class Test {
public:int _a;
public:Test(int a) {_a = a;}Test* operator&() {cout << this << endl;return this;}
};int main() {Test t1(0);Test* pt = &t1;pt = t1.operator&();
}

6.const对象取地址操作符重载

const对象取地址是无法调用代码二十一中的函数的,下面代码可以验证。因为const对象是不允许被修改的,普通的取地址可能会试图修改const对象中的内容,所以需要设置相应的措施。

代码二十二:注意const对象取地址函数格式:const 类名 * operator &()const{}

红色const代表这是一个const成员函数,在该函数内部不能修改任何成员变量。红色const实际上是修饰函数隐含的this指针,表面在该成员函数中不能对类的任何成员进行修改。

   普通成员函数中this的类型:类名 * const this。代表this的指向不可以修改,但this指向的空间中的内容可以修改。

const成员函数中this的类型:const 类名 * const this。代表this的指向不能修改,指向空间中的内容也不可以修改。

关于上述const与指针结合的意义,在我的《快速理解const修饰指针》中有讲解,不了解的可以看看。

要点:

1.普通对象可以调用普通的成员函数和const成员函数。

        2.const成员只能调用const成员函数。

        3.普通成员函数可以调用const成员函数。

        4.const成员函数不能调用普通成员函数。

        5.当const成员函数中还想修改成员变量时,在成员变量的定义前面加mutable关键字。如代码二十三。

代码二十二:

//代码二十二
#include "iostream"
using namespace std;class Test {
public:int _a;
public:Test(int a) {_a = a;}Test* operator&() {cout << "普通取地址" << endl;return this;}const Test* operator&()const {cout << "const取地址" << endl;return this;}
};int main() {Test t1(0);const Test t2(1);&t1;//输出 普通取地址&t2;//输出 const取地址
}

代码二十三:

//代码二十三
#include "iostream"
using namespace std;class Test {
public:mutable int _a;
public:Test(int a) {_a = a;}void Chage()const {_a = 16;}
};int main() {Test t1(0);t1.Chage();cout << t1._a << endl;//输出 16
}

C++类与对象(二) 六个默认成员函数相关推荐

  1. 一文带你入门C++,类与对象、6个默认成员函数、this指针以及static关键字。

    C++98关键字:63个 一.命名空间规则(namespace) 1.命名空间可以解决函数.全局变量名重复的问题,包在不同的命名空间里的重复函数,实际就是两个完全无关的函数. 2.命名空间允许续嵌套: ...

  2. 【类和对象(中)】六大默认成员函数

    文章目录 前言 一.

  3. 【C++】类和对象【中篇】--C++六个默认成员函数以及const成员函数

    文章目录 一.类的6个默认成员函数 二.构造函数 1.概念 2.特性 2.1特征分析--自动生成 2.2.特征分析--选择处理 2.3特征分析--默认构造 3.C++11补丁--缺省值 三.析构函数 ...

  4. 继承和多态 2.0 -- 继承的六个默认成员函数

    本文重要介绍普通继承中如何写派生类的六个默认成员函数,主要是针对在派生类中,如何调用基类的六个默认成员函数 需要说明的一点就是,如果子类中没有调用父类的函数时,系统会自动生成一个. 构造函数 子类中有 ...

  5. 《C++类基本知识和6个默认成员函数详细剖析》

    面向对象编程–类的认识 之前我们学习了C语言知识,C语言是一种面向过程的程序设计语言,而C++语言呢是基于面向对象的一种程序设计语言,关注的是对象,即将一件事情拆分成不同的对象,靠对象间的交互完成.接 ...

  6. [c++ 简单的笔记] 类的6个默认成员函数

    -客亦知夫水与月乎? -哀吾生之须臾 羡长江之无穷. 文章目录 类的6个默认成员函数 构造函数 构造函数初始化列表 注意 explicit关键字(了解) 拷贝构造函数 务必自己写深拷贝的情况的情况 赋 ...

  7. 【C++】默认成员函数

    前言 一.什么是默认成员函数 二.构造函数 三.析构函数 四.拷贝构造 五.赋值运算符重载 六.const成员 七.&运算符重载(了解) 总结: 前言 这一节主要讲四个默认成员函数.运算符重载 ...

  8. C++11-列表初始化/变量类型推导/范围for/finaloverride/默认成员函数控制

    C++11-列表初始化/变量类型推导/范围for/final&override/默认成员函数控制 零.前言 一.C++11简介 二.列表初始化 1.内置类型列表初始化 2.自定义类型列表初始化 ...

  9. c 类别构造函数需要包含所有成员吗_C++默认成员函数解析

    1.什么是面向对象? 概念:(Object Oriented Programming,缩写:OOP)是一种程序设计范型,同时也是一种程序开发的方法. 对象指的是类的实例,将对象作为程序的基本单元,将程 ...

最新文章

  1. 家用轿车轮胎多久更换一次?
  2. 【记录】vmware fusion 7 windows 10 unidentified network
  3. 反思深度思考:预热[准备] 高密度[压力专注] 辨真伪[冷静分析] 反推[灵活] 结构化[全局]
  4. Python:Matplotlib 画曲线和柱状图(Code)
  5. 通信工程施工图案例分析
  6. DRDS分布式SQL引擎—执行计划介绍
  7. 计算机boot进入u盘启动,暗影精灵5怎么设置u盘启动 暗影精灵5设置u盘启动方法...
  8. [leetcode] 24. Swap Nodes in Pairs
  9. w ndows10电脑配置看哪里,win10对电脑配置要求及如何查看电脑配置
  10. 图像局部特征(六)--斑点检测之SIFT算法原理总结补充
  11. 2021-09-09321. 拼接最大数 单调栈
  12. 工程模式写入imei_开发初期IMEI号的写入
  13. Linux下安装vim编辑器
  14. 如何充分利用点赞功能提升Linkedin账号曝光率和活跃度
  15. swift4.0 方法监听Selector写法总结
  16. 视频剪辑完成,应该如何给视频配音?三种配音方法快来学
  17. 图嵌入综述 (arxiv 1709.07604) 译文 4.3 ~ 4.7
  18. Android 是Google开发的基于Linux平台的开源手机操作系统
  19. 计算机登录界面没有用户显示不出来,win10不出现登录界面怎么办
  20. 卡尔曼滤波之目标跟踪

热门文章

  1. [freecodecamp]电话号码检查器
  2. G宝盘-1GB的免费网络U盘
  3. php发表说说,发表qq说说的句子
  4. 百度云获取下载链接代码。
  5. html文本框默认信息,如何使HTML文本框默认
  6. 效能评估系统解决方案
  7. 拼写检查 java_一个简单的拼写检查器
  8. SQL中对于关系除法的理解
  9. Vue(四)——使用脚手架(1)
  10. Tableau 超市经典案例之销售分析(三)