C++:类中两个易被忽略的默认函数

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

一、取地址函数

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

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

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

 1 #include<iostream>
 2 #include<string>
 3 using namespace std;
 4 class Student{
 5 public:
 6     Student(){
 7         cout<<"调用无参数的构造函数"<<endl;
 8     }
 9     Student(string name,int age):Name(name),Age(age){
10         cout<<"调用有参数的构造函数"<<endl;
11     }
12     Student(const Student& stu){
13         cout<<"调用拷贝构造函数"<<endl;
14         Name=stu.Name;
15         Age=stu.Age;
16     }
17     Student& operator=(const Student& stu){
18         cout<<"调用赋值函数"<<endl;
19         if(this!=&stu){
20             Name=stu.Name;
21             Age=stu.Age;
22         }
23         return *this;
24     }
25     ~Student(){
26         cout<<"调用析构函数"<<endl;
27     }
28 private:
29     string Name;
30     int Age;
31 };
32 int main(){
33     Student stu("Tomwenxing",23);
34     cout<<"对象stu的地址为:"<<&stu<<endl;//成功:运行对对象stu进行取地址操作 
35     return 0;
36 }

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

 1 #include<iostream>
 2 #include<string>
 3 using namespace std;
 4 class Student{
 5 public:
 6     Student(){
 7         cout<<"调用无参数的构造函数"<<endl;
 8     }
 9     Student(string name,int age):Name(name),Age(age){
10         cout<<"调用有参数的构造函数"<<endl;
11     }
12     Student(const Student& stu){
13         cout<<"调用拷贝构造函数"<<endl;
14         Name=stu.Name;
15         Age=stu.Age;
16     }
17     Student& operator=(const Student& stu){
18         cout<<"调用赋值函数"<<endl;
19         if(this!=&stu){
20             Name=stu.Name;
21             Age=stu.Age;
22         }
23         return *this;
24     }
25     Student* operator&(){ //取地址函数
26         cout<<"调用取地址函数"<<endl;
27         return this;
28     }
29     ~Student(){
30         cout<<"调用析构函数"<<endl;
31     }
32 private:
33     string Name;
34     int Age;
35 };
36 int main(){
37     Student stu("Tomwenxing",23);
38     cout<<"对象stu的地址为:"<<&stu<<endl;//成功:运行对对象stu进行取地址操作,该语句相当于stu.operator&();
39     return 0;
40 }

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

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

 1 #include<iostream>
 2 #include<string>
 3 using namespace std;
 4 class Student{
 5 public:
 6     Student(){
 7         cout<<"调用无参数的构造函数"<<endl;
 8     }
 9     Student(string name,int age):Name(name),Age(age){
10         cout<<"调用有参数的构造函数"<<endl;
11     }
12     Student(const Student& stu){
13         cout<<"调用拷贝构造函数"<<endl;
14         Name=stu.Name;
15         Age=stu.Age;
16     }
17     Student& operator=(const Student& stu){
18         cout<<"调用赋值函数"<<endl;
19         if(this!=&stu){
20             Name=stu.Name;
21             Age=stu.Age;
22         }
23         return *this;
24     }
25     Student* operator&(){
26         cout<<"调用取地址函数"<<endl;
27         return this;
28     }
29     ~Student(){
30         cout<<"调用析构函数"<<endl;
31     }
32 private:
33     string Name;
34     int Age;
35 };
36 int main(){
37     const Student stu("Tomwenxing",23);
38     cout<<"对象stu的地址为:"<<&stu<<endl;//成功:运行对对象stu进行取地址操作
39     return 0;
40 }

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

 1 #include<iostream>
 2 #include<string>
 3 using namespace std;
 4 class Student{
 5 public:
 6     Student(){
 7         cout<<"调用无参数的构造函数"<<endl;
 8     }
 9     Student(string name,int age):Name(name),Age(age){
10         cout<<"调用有参数的构造函数"<<endl;
11     }
12     Student(const Student& stu){
13         cout<<"调用拷贝构造函数"<<endl;
14         Name=stu.Name;
15         Age=stu.Age;
16     }
17     Student& operator=(const Student& stu){
18         cout<<"调用赋值函数"<<endl;
19         if(this!=&stu){
20             Name=stu.Name;
21             Age=stu.Age;
22         }
23         return *this;
24     }
25     Student* operator&(){
26         cout<<"调用取地址函数"<<endl;
27         return this;
28     }
29     const Student* operator&() const{
30         cout<<"调用对常对象的取地址函数"<<endl;
31         return this;
32     }
33     ~Student(){
34         cout<<"调用析构函数"<<endl;
35     }
36 private:
37     string Name;
38     int Age;
39 };
40 int main(){
41     const Student stu("Tomwenxing",23);
42     cout<<"对象stu的地址为:"<<&stu<<endl;//成功:运行对常对象stu进行取地址操作
43     return 0;
44 }

特别注意:两个const的作用

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

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

时间: 2025-01-05 03:56:10

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

友元——友元可以访问与其有好友关系的类中的私有成员。 友元包括友元函数和友元类。

简介:友元可以访问与其有好友关系的类中的私有成员.    友元包括友元函数和友元类. [1]将普通函数声明为友元函数 #include<iostream> using namespace std; class Time { public: Time(int,int,int); friend void display(Time &);//定义友元函数 private: int hour; int minute; int sec; }; Time::Time(int h,int m,int

回调函数中调用类中的非静态成员变量或非静态成员函数

有关这方面的问题,首先说一点: 回调函数必须是静态成员函数或者全局函数来实现回调函数,大概原因是普通的C++成员函数都隐含了一个函数参数,即this指针,C++通过传递this指针给成员函数从而实现函数可以访问类的特定对象的数据成员.由于this指针的原因,使得一个普通成员函数作为回调函数时就会因为隐含的this指针问题使得函数参数个数不匹配,从而导致回调函数编译失败. 基于上面的理论,如何在类中封装回调函数呢? 回调函数只能是全局函数或者静态成员函数,但是由于全局函数会破坏封装性,所以只能用静

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

C++类中谈到static,我们可以在类中定义static成员,static成员函数!C++primer里面讲过:static成员它不像普通的数据成员,static数据成员独立于该类的任意对象而存在,每个static数据成员是与类关联的对象,并不与该类的对象相关联!这句话可能比较拗口,其实可以这么理解:每个static数据成员可以看成是类的一个对象,而不与该类定义的对象有任何关系!下面我们就来具体看看类中的static数据成员! 谈到数据成员,我们最先想到的应该是怎么去定义一个static数据成

一个空类被编译器编译后产生了哪些默认函数

为何空类的大小不是0呢? 为了确保两个不同对象的地址不同,必须如此. 类的实例化是在内存中分配一块地址,每个实例在内存中都有独一无二的二地址. 同样,空类也会实例化,所以编译器会给空类隐含的添加一个字节,这样空类实例化后就有独一无二的地址了. 所以,空类的sizeof为1,而不是0. 一个空的class在C++编译器处理过后就不再为空,编译器会自动地为我们声明一些member function, 如果你写 class A{}; 编译器处理后,就相当于: class A { public: A()

nginx中try_files参数易被忽略的知识点

先创建测试目录与文件 mkdir -p /php/aaa/bbbvim /php/aaa/index.html <h1>small try</h1> 配置nginx server server { listen 80; server_name www.ready.org; location / { root /php; try_files $uri $uri/ /index.php; index index.html index.htm; } location ~ .*\.(php

概率论中两个易混淆概念(概率分布函数 VS. 概率密度函数)

随机变量的分布函数: 1. 定义 设X是一个随机变量,x是任意实数,函数F(x)=P{X<=x}称为X的分布函数. 2.1 性质 对于任意x1,x2,P{X<=x2}-P{X<=x1}=F(x2)-F(x1),因此分布函数描述了随机变量的统计规律性. 2.2 性质 对于连续型随机变量P{X=a}=0,在这里事件{X=a}并非是不可能事件,但有P{X=a}=0. 随机变量的密度函数: 1. 定义 如果对于随机变量X的分布函数F(x),存在非负函数f(x),使得对于任意实数有 ,则称X为连续

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

如下 import numpy a = [1, 2, 3, 4] b = [5, 6, 7, 8] a_array = numpy.array(a) b_array = numpy.array(b) c_array = a_array + b_array d_array = a_array - b_array print c_array print d_array 原文地址:https://www.cnblogs.com/robinunix/p/9670942.html

Python之编写测试用例,unittest模块中的TestCase类中的六种断言方法,以及setUp()函数。

unittest是Python自带的标准库中的模块,其中包括: 1.TestCase类 2.TestSuite类 3.TestLoader类 4.TextTestRunner类 5.TextTestResult类 下面是TestCase中的六种断言方法的测试用例. # -*- coding:UTF-8 -*- import unittestclass TestStringMethods(unittest.TestCase): def test_one(self): '''测试两个字符串是否相等'

spring-在切面类中定义私有方法解决重复编写execution函数

一.创建项目    项目名称:spring101002二.添加jar包    1.在项目中创建lib目录        /lib    2.在lib目录下添加相关spring jar包        --用于AspectJ        com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar        spring-aspects-3.2.0.RELEASE.jar        --用于切面编程        com.springsour