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. 1025 反转链表(链表,reverse)

    题目: 给定一个常数 K 以及一个单链表 L,请编写程序将 L 中每 K 个结点反转.例如:给定 L 为 1→2→3→4→5→6,K 为 3,则输出应该为 3→2→1→6→5→4:如果 K 为 4,则 ...

  2. 利用canvas将网页元素生成图片并保存在本地

    利用canvas将网页元素生成图片并保存在本地 首先引入三个文件: 1.<script type="text/javascript" src="js/html2ca ...

  3. SpringBoot与mongodb的结合

    本文系列文章: ​ 使用Shell 操作 MongoDB的技巧 ​ MongoTemplate的使用技巧及其注意事项 敬请期待. 前言 最近公司想要做一个用户行为数据的收集,最开始想用mysql来存储 ...

  4. Delphi泛型动态数组的扩展--转贴

    此文章转载于http://www.raysoftware.cn/?p=278&tdsourcetag=s_pcqq_aiomsg的博客 从Delphi支持泛型的第一天起就有了一种新的动态数组类 ...

  5. Scala的类继承

    Scala的类继承 extend Scala扩展类的方式和java一样使用extends关键字 class Employee extends Person { } 与java一样,可以在定义的子类重写 ...

  6. Vue Router的入门以及简单使用

    Vue Router 是Vue官方的路由管理器,是Vue用来实现SPA的插件.它和 Vue.js 的核心深度集成,让构建单页面应用(SPA)变得易如反掌. 基本概念: 路由:是一种映射关系,是 “pa ...

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

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

  8. c++ 字符串和字符串库函数

    //有2个字符串定义如下: //char s1[38]="www.yjxsoft"; //char s2[]=".com"; //请编写一段代码,把字符串s2追 ...

  9. Luogu5110 块速递推

    题面 题解 线性常系数齐次递推sb板子题 $a_n=233a_{n-1}+666a_{n-2}$的特征方程为 $$ x^2=233x+666 \\ x^2-233x+666=0 \\ x_1=\fra ...

  10. 【JLOI2013】卡牌游戏

    题面 题解 概率$dp$ 设$f[i][j]$表示还剩$i$个人时,第$j$个人获胜的概率. 边界$f[1][1] = 1$ 转移: 枚举庄家抽到的卡牌$k$,得到这一轮被淘汰的位置$c$. 可以知道 ...