C++的自定义类中有六个默认的函数,即如果用户没有显式定义这些函数时,C++编译器会类中生成这些函数的默认形式。除了大家所熟知的构造函数、拷贝构造函数、赋值函数析构函数外,C++为自定义类 还提供了两个容易被人忽视的默认函数——取地址函数对常对象的取地址函数。

一、取地址函数

在C++中可以通过取地址运算符&求得变量的地址,如:

 int a=;
cout<<"变量a的地址为:"<<&a<<endl;

那么对于自定义类的对象是否可以通过取地址运算符&求得对象在内存中的地址呢?我们先来看个例子:

 #include<iostream>
#include<string>
using namespace std;
class Student{
public:
Student(){
cout<<"调用无参数的构造函数"<<endl;
}
Student(string name,int age):Name(name),Age(age){
cout<<"调用有参数的构造函数"<<endl;
}
Student(const Student& stu){
cout<<"调用拷贝构造函数"<<endl;
Name=stu.Name;
Age=stu.Age;
}
Student& operator=(const Student& stu){
cout<<"调用赋值函数"<<endl;
if(this!=&stu){
Name=stu.Name;
Age=stu.Age;
}
return *this;
}
~Student(){
cout<<"调用析构函数"<<endl;
}
private:
string Name;
int Age;
};
int main(){
Student stu("Tomwenxing",);
cout<<"对象stu的地址为:"<<&stu<<endl;//成功:运行对对象stu进行取地址操作
return ;
}

由上面的例子可知,C++允许通过取地址运算符&求得对象在内存中的地址,而这个功能就是依靠类中的取地址函数实现的。和赋值函数相似,类中的取地址函数是通过对取地址运算符&进行重载来实现的,如果用户在编写类时没有显式地定义类的取地址函数,那么C++编译器将会在类中生成一个默认的取地址函数。

 #include<iostream>
#include<string>
using namespace std;
class Student{
public:
Student(){
cout<<"调用无参数的构造函数"<<endl;
}
Student(string name,int age):Name(name),Age(age){
cout<<"调用有参数的构造函数"<<endl;
}
Student(const Student& stu){
cout<<"调用拷贝构造函数"<<endl;
Name=stu.Name;
Age=stu.Age;
}
Student& operator=(const Student& stu){
cout<<"调用赋值函数"<<endl;
if(this!=&stu){
Name=stu.Name;
Age=stu.Age;
}
return *this;
}
25 Student* operator&(){ //取地址函数
26 cout<<"调用取地址函数"<<endl;
27 return this;
28 }
~Student(){
cout<<"调用析构函数"<<endl;
}
private:
string Name;
int Age;
};
int main(){
Student stu("Tomwenxing",);
cout<<"对象stu的地址为:"<<&stu<<endl;//成功:运行对对象stu进行取地址操作,该语句相当于stu.operator&();
return ;
}

二、对常对象的取地址函数

还是上面的例子,这次我们队常对象进行取地址操作,看看会发生什么:

 #include<iostream>
#include<string>
using namespace std;
class Student{
public:
Student(){
cout<<"调用无参数的构造函数"<<endl;
}
Student(string name,int age):Name(name),Age(age){
cout<<"调用有参数的构造函数"<<endl;
}
Student(const Student& stu){
cout<<"调用拷贝构造函数"<<endl;
Name=stu.Name;
Age=stu.Age;
}
Student& operator=(const Student& stu){
cout<<"调用赋值函数"<<endl;
if(this!=&stu){
Name=stu.Name;
Age=stu.Age;
}
return *this;
}
25 Student* operator&(){
26 cout<<"调用取地址函数"<<endl;
27 return this;
28 }
~Student(){
cout<<"调用析构函数"<<endl;
}
private:
string Name;
int Age;
};
int main(){
const Student stu("Tomwenxing",);
cout<<"对象stu的地址为:"<<&stu<<endl;//成功:运行对对象stu进行取地址操作
return ;
}

通过上面的例子我们发现,在对常对象stu进行取地址操作时,对象并没有调用类中的取地址函数,这是因为类中还有一个默认的函数,其功能是对常对象进行取地址操作。和取地址函数相同,对常对象的取地址函数也是通过对取地址运算符&重载来实现的,同样如果用户在编写类时没有显式地定义类的对常对象的取地址函数,那么C++编译器将会在类中生成一个默认的对常对象的取地址函数

 #include<iostream>
#include<string>
using namespace std;
class Student{
public:
Student(){
cout<<"调用无参数的构造函数"<<endl;
}
Student(string name,int age):Name(name),Age(age){
cout<<"调用有参数的构造函数"<<endl;
}
Student(const Student& stu){
cout<<"调用拷贝构造函数"<<endl;
Name=stu.Name;
Age=stu.Age;
}
Student& operator=(const Student& stu){
cout<<"调用赋值函数"<<endl;
if(this!=&stu){
Name=stu.Name;
Age=stu.Age;
}
return *this;
}
25 Student* operator&(){
26 cout<<"调用取地址函数"<<endl;
27 return this;
28 }
29 const Student* operator&() const{
30 cout<<"调用对常对象的取地址函数"<<endl;
31 return this;
32 }
~Student(){
cout<<"调用析构函数"<<endl;
}
private:
string Name;
int Age;
};
int main(){
const Student stu("Tomwenxing",);
42 cout<<"对象stu的地址为:"<<&stu<<endl;//成功:运行对常对象stu进行取地址操作
return ;
}

特别注意:两个const的作用

• 第一个const要求函数返回的指针是常量,如果返回的是非常量则报错

• 第二个const修饰this指针,使该对象的this指针是一个指针常量,从而能够被该函数成功返回。

C++:类中两个易被忽略的默认函数的更多相关文章

  1. httpservlet类中两个service方法

    在浏览器访问html页面时,当数据提交给servlet时发生了什么,这是我们需要了解的. 1.我们需要了解一下servlet的继承体系. servlet接口 ------->GenericSer ...

  2. C++类中的static数据成员,static成员函数

    C++类中谈到static,我们可以在类中定义static成员,static成员函数!C++primer里面讲过:static成员它不像普通的数据成员,static数据成员独立于该类的任意对象而存在, ...

  3. python类中两个列表实例如何相加或相减

    如下 import numpy a = [1, 2, 3, 4] b = [5, 6, 7, 8] a_array = numpy.array(a) b_array = numpy.array(b) ...

  4. 解决同一页面中两个iframe互相调用jquery,js函数

    这一个月又没更新博客,唉,懒癌又犯了,今天解决了一个问题,关于两个iframe互相调用jquery函数方法 a.html中有两个iframe,如下: <iframe width="10 ...

  5. cocos2dx lua 绑定之二:手动绑定自定义类中的函数

    cococs2dx 3.13.1 + vs2013 + win10 1.首先按照<cocos2dx lua 绑定之一:自动绑定自定义类>绑定Student类 2.在Student类中增加一 ...

  6. python: 面向对象:类和对象调用类中的变量和方法

    一. 面向对象初识 我们在生活中做事都是面向过程的,前面实现一些基本逻辑功能代码也是用面向过程的语句实现的,后来学了函数,把这些功能又装到了函数里.但用面向过程的方法去写程序,只能实现一个功能,我们要 ...

  7. [Python之路] object类中的特殊方法

    一.object类的源码 python版本:3.8 class object: """ The most base type """ # d ...

  8. spring boot:使用validator做接口的参数、表单、类中多字段的参数验证(spring boot 2.3.1)

    一,为什么要做参数验证? 永远不要相信我们在后端接收到的数据, 1,防止别人通过接口乱刷服务:有些不怀好意的人或机构会乱刷我们的服务,例如:短信接口, 相信大家可能很多人在工作中遇到过这种情况 2,防 ...

  9. C++:调整基类成员在派生类中的访问属性的其他方法(同名成员和访问声明)

    4.3 调整基类成员在派生类中的访问属性的其他方法 4.3.1 同名函数 在定义派生类的时候,C++语言允许在派生类中说明的成员与基类中的成员名字相同,也就是 说,派生类可以重新说明与基类成员同名的成 ...

随机推荐

  1. 4.使用Jackson将Json数据转换成实体数据

    Jar下载地址:http://jackson.codehaus.org/ 注意: 一.类中的属性名称一定要和Json数据的属性名称一致(大写和小写敏感),类之间的嵌套关系也应该和Json数据的嵌套关系 ...

  2. Centos 模拟生成文件的脚本

    #!/bin/sh count= #控制每秒写入不同大小的文件 while true do ;i<=$count;i++)) do /bin/-`.jpg done ;i<=$count; ...

  3. Linux开机自启动脚本

    将需要开机自启动的脚本命令写在文件/etc/rc.d/rc.local中即可. 比如需要开机自启动MySql和Apache,则在/etc/rc.d/rc.local文件尾部加入两行命令: system ...

  4. 安装luasocket 的正确姿势

    在lua中用下面这种方式使用socket,安装luasocket-2.0.2后老是报一些莫名其妙的错误. require("socket") 下面是部分报错信息 lua: erro ...

  5. nginx如何做到TCP的负载均衡

    原文:https://blog.csdn.net/u011218159/article/details/50966861   TCP 的 负载均衡   这个片段描述了如何通过nginx plus进行负 ...

  6. Java基础—IO小结(一)概述与节点流

    一.File类的使用  由于file类是一个基础类,所以我们从file类开始了解.(SE有完善的中文文档,建议阅读) 构造器: 常用方法:——完整方法请参见API API API!!! File做的是 ...

  7. 成都Uber优步司机奖励政策(4月24日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  8. Jquery 实现select 3级级联查询

    实现级联效果的思路: 1. 页面加载时,先显示第一级select,第二.三级的select隐藏,根据第一级select值的改变,再显示第二级select,依次类推: 2.只从后台获取第一级select ...

  9. P4048 [JSOI2010]冷冻波

    出题人你tm搞笑呢,冰霜新星翻成冷冻波,而且tm就只能打一只小精灵???巫妖王都想来砍死你 首先要搞出每个巫妖能不能打到每一个小精灵,然后二分时间,就能算出每个巫妖可以打的次数,网络流check即可 ...

  10. Linux新手常见问题

    yum与apt的区别 参考:https://blog.csdn.net/qq_26182553/article/details/79869666 ubuntu下su: Authentication f ...