C++:类中两个易被忽略的默认函数
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++:类中两个易被忽略的默认函数的更多相关文章
- httpservlet类中两个service方法
在浏览器访问html页面时,当数据提交给servlet时发生了什么,这是我们需要了解的. 1.我们需要了解一下servlet的继承体系. servlet接口 ------->GenericSer ...
- C++类中的static数据成员,static成员函数
C++类中谈到static,我们可以在类中定义static成员,static成员函数!C++primer里面讲过:static成员它不像普通的数据成员,static数据成员独立于该类的任意对象而存在, ...
- python类中两个列表实例如何相加或相减
如下 import numpy a = [1, 2, 3, 4] b = [5, 6, 7, 8] a_array = numpy.array(a) b_array = numpy.array(b) ...
- 解决同一页面中两个iframe互相调用jquery,js函数
这一个月又没更新博客,唉,懒癌又犯了,今天解决了一个问题,关于两个iframe互相调用jquery函数方法 a.html中有两个iframe,如下: <iframe width="10 ...
- cocos2dx lua 绑定之二:手动绑定自定义类中的函数
cococs2dx 3.13.1 + vs2013 + win10 1.首先按照<cocos2dx lua 绑定之一:自动绑定自定义类>绑定Student类 2.在Student类中增加一 ...
- python: 面向对象:类和对象调用类中的变量和方法
一. 面向对象初识 我们在生活中做事都是面向过程的,前面实现一些基本逻辑功能代码也是用面向过程的语句实现的,后来学了函数,把这些功能又装到了函数里.但用面向过程的方法去写程序,只能实现一个功能,我们要 ...
- [Python之路] object类中的特殊方法
一.object类的源码 python版本:3.8 class object: """ The most base type """ # d ...
- spring boot:使用validator做接口的参数、表单、类中多字段的参数验证(spring boot 2.3.1)
一,为什么要做参数验证? 永远不要相信我们在后端接收到的数据, 1,防止别人通过接口乱刷服务:有些不怀好意的人或机构会乱刷我们的服务,例如:短信接口, 相信大家可能很多人在工作中遇到过这种情况 2,防 ...
- C++:调整基类成员在派生类中的访问属性的其他方法(同名成员和访问声明)
4.3 调整基类成员在派生类中的访问属性的其他方法 4.3.1 同名函数 在定义派生类的时候,C++语言允许在派生类中说明的成员与基类中的成员名字相同,也就是 说,派生类可以重新说明与基类成员同名的成 ...
随机推荐
- start_kernel之前的汇编代码分析
start_kernel之前的汇编代码分析 Boot中执行下面两句话之后,进入uclinux内核. theKernel = (void (*)(int, int, unsigned int))((ui ...
- bat设置windows计划任务
设置定时任务 @echo off set NAME=dailybackup :: set DAY=MON,TUE,WED,THU,FRI,SAT,SUN set COMMAND=cscript.exe ...
- 苹果电脑(Mac mini或Macbook或iMac)恢复出厂设置
苹果电脑(Mac mini或Macbook或iMac)恢复出厂设置,首先要做好如下的准备: 第一:数据的备份:第二:保证正常的wifi连接:第三:有线的鼠标键盘连接: 具体恢复操作步骤: 步骤一:电脑 ...
- C语言学习记录_2019.02.08
\n:换行: \t:制表符,相当于大空格: a[5]={2};<------->a[5]={2,0,0,0,0}; 数组初始化的方法:a[5]={0};即全部初始化为0: 数组初始化的 ...
- Modelsim SE自动化仿真——如何将.do文件中自定义的库链接到testbench顶层模块
我们用Modelsim SE进行仿真时,为了方便,一般会编写.do文件来启动当前仿真.关于.do文件的编写,一般网上都有成型的模板,我们只要稍微改几个参数,就可以符合我们的仿真需求了.但是如果仿真时需 ...
- UWP Test Webview JS interact, new window open (新窗口打开)
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Run ...
- ISP与IAP
ISP:in system program 顾名思义,在系统编程,单片机不用从电路上拆下,直接用下载器或者串口即可完成程序的烧写.这个是用于工程师调试程序,或者出厂时烧写程序.本质上是芯片出厂时烧录到 ...
- Hbase操作table常见方法示例
首先上我的输出类: /** * 功能:电池历史数据数据结构 * Created by liuhuichao on 2016/12/5. */ public class ResBatteryDataHi ...
- 【Maven】在pom.xml文件中使用resources插件的小作用
在spring boot创建web项目打包为jar包的过程中,是不会把webapp目录下的页面也打包进去的,这个时候接触到了maven的 resources插件. ================== ...
- ssm 配置事务回滚
参考:https://blog.csdn.net/Mint6/article/details/78363761 在 applicationContext.xml 中配置好了事务和数据源等必须要用到的配 ...