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++语言允许在派生类中说明的成员与基类中的成员名字相同,也就是 说,派生类可以重新说明与基类成员同名的成 ...
随机推荐
- 火狐下不能使用非行间样式currentStyle用getComputedStyle获取
用js的style属性可以获得html标签的样式,但是不能获取非行间样式.那么怎么用js获取css的非行间样式呢?在IE下可以用currentStyle,而在火狐下面我们需要用到getComputed ...
- 文本处理三剑客之 grep/egrep
grep:文本过滤工具 支持BRE egrep: 支持ERE fgrep: 不支持正则 作用:根据用户指定的“模式”,对目标文本逐行进行匹配检查,打印匹配到的行 模式:由正则表达式字符及文本字符所编写 ...
- webpack / vue项目 config/index.js配置(用于配置webpack服务器代理)
'use strict' // Template version: 1.1.3 // see http://vuejs-templates.github.io/webpack for document ...
- Linux—文件命令之touch命令
下面总结一下对于文件的操作命令: satat命令:用于显示文件的详细信息,包括文件.设备.gid.各种时间等. 命令格式:stat filename touch 的两个功能: 1.新建文件,如需建立特 ...
- 如何防止网页被植入广告,内容被监控-HTTPS
前几天一朋友说访问网站页面底部怎么出现小广告了呢,内容有点不雅,朋友截图发给我,调侃我说怎么放这种广告,我一听纳闷,网站运行伊始,从来没有投放过任何广告,更别说不雅广告了. 最近还遇到一个问题就是,网 ...
- SEO优化上首页之搜索引擎蜘蛛Spider原理
Spider,蜘蛛,又名网页网络爬虫.网络机器人,是按照一定策略不断抓取互联网网页的特定程序.蜘蛛抓回的页面创建索引后参与排名,等待用户检索.为了网站优化自然排名上首页,精灵儿工作室下面详细剖析Spi ...
- vb6 读写文件
'--------------------------------- 'write file Dim nHandle As Integer, fName As String fName ...
- [arc081F]Flip and Rectangles-[黑白染色]
Description 传送门 Solution 有一个神秘的结论..我不知道大佬是怎么场上推出来的. 一个黑白染色图,每次可以任意翻转行或列的颜色,如果每个2*2的子矩阵内黑色格子都是偶数个,则可以 ...
- jQuery学习-页面就绪函数
1.开发工具HBuilder <!DOCTYPE html> <html> <head> <meta charset="utf-8" /& ...
- kali更新后窗口不能适应屏幕的解决方案
终端执行 systemctl restart open-vm-tools 当然,也可以加入到启动项来实现自启动