首页 > 其他分享 >成员函数

成员函数

时间:2023-08-23 20:33:51浏览次数:26  
标签:函数 对象 成员 拷贝 指针 赋值

一、对象的创建和销毁过程

Ⅰ.对象的创建过程
  1. 给对象划分内存空间

  2. 执行初始化列表
    ①根有参构造据继承表的顺序调用父类的无参构造或者

    通过:父类名(val)    调用父类的有参构造
    

    ②根据成员变量的定义顺序调用类类型成员的无参构造或有参构造

    通过:类类型命成员(val)  调用类类型成员的有参构造
    

    ③对其他成员进行初始化

  3. 执行自己的构造函数,可能去申请资源

Ⅱ.对象执行的销毁过程(创建的逆序)
  1. 执行自己的析构函数,可能去释放资源

  2. 根据类类型成员的逆序,调用他们的析构函数

  3. 根据继承表的顺序,调用父类的析构函数

  4. 释放对象的内存

二、成员函数是如何区分调用它的对象-使用隐藏的this指针

  • 对象的内存只存储了成员变量,没有存储成员函数指针,相当于

  • 当对象调用成员函数时,编译器会自动把对象的地址传递给该成员函数,也就是说普通的成员函数中都有一个隐藏的参数,该参数叫做this指针,this指针用来接收调用对象的地址

  • this指针拿到了调用对象的地址后,就可以直接访问该对象的成员,完成区分对象任务

  • 虽然this指针隐藏定义,但是可以显式的使用它,但不能多此一举的显式定义它

三、常函数

  1. 被const修饰了this指针的成员函数,称为常函数

  2. 当对象调用成员函数时,编译器会隐式的把对象地址传递给成员函数

  3. 当对象被const修饰过具有常属性,就不能直接调用普通成员函数,因为传递的对象地址也具有常属性,而普通成员函数的this指针参数不具备常属性,所以编译器会报错,C++编译器不允许带常属性的数据给不带常属性的变量赋值

  4. 因此需要让成员函数中的this也具备常属性,通过const修饰变成常函数,所以const修饰的是this指针

    返回值 类名::成员函数(参数列表)const
    {
        ```
    }
    
  5. 具有常属性的对象只能调用常函数,常函数中也只能调用常函数;不具有常属性的对象都可以调用

  6. 同名的成员函数,如果其他参数列表完全相同,但是常属性不同,也可以构成重载

  7. 正常情况下在常函数中不能修改成员变量,除非该成员在定义时通过mutable修饰

面试问题:
  1. const在C和C++中的相同点和不同点?
    ①相同点
    const在C和C++中都用来“显示”地保护数据不被修改
    ②不同点

    a.C++编译器会优化const变量的取值过程,哪怕该变量的内存被强行修改,也不会改变通过变量访问的数值,这种机制会更安全,但C语言编译器不会优化
    b.在C++中const还可以用于修饰成员函数的this指针,从而定义常函数
    
  2. 一个空的结构体在C语言、C++分别占多少字节?为什么?
    C语言中占0字节,C++中占1字节
    在C++结构体中可以定义成员函数,并且默认有四个隐藏的成员函数,当对象去调用成员函数时,需要传递对象的地址给成员函数,所以这套机制要求结构对象需要在内存中有一席之地,如果结构中没有任何的成员变量,编译器会让结构至少拥有1字节的不使用的内存,让上面这套机制自洽

四、拷贝构造

  • 拷贝构造就是一种特殊版本的构造函数,格式为

    类名(const 类名& that)
    {
        ```
    }
    
  • 什么时候会调用拷贝构造:
    当使用旧对象给新对象初始化时,会自动调用拷贝构造

    Test t1;        //调用无参构造
    Test t2 = t1;    //调用拷贝构造
    Test t3(t2);     //调用拷贝构造                                                                             
    
  • 拷贝构造的任务:
    负责把旧对象中的成员变量拷贝给

  • 什么时候需要显式地写拷贝构造?
    普通情况下编译器自动生成的拷贝构造完全够用,但当类中有成员是指针类型且为该指针成员分配了堆内存,如果使用默认自动生成的拷贝构造只会对指针的值进程拷贝,此时就会导致两个对象的指针成员指向同一块内存,所以在执行析构函数时会造成重复释放错误,此时应该显式地实现拷贝构造函数

  • 浅拷贝和深拷贝
    浅拷贝:当类中的成员有指针且分配堆内存,只拷贝指针变量的值
    深拷贝:不拷贝指针变量的值,而是拷贝指针变量所指向的内存的内容

五、赋值操作(拷贝赋值、赋值运算符)

  • 任务:用一个旧对象给另一个旧对象赋值(两个对象都已经完成创建)

  • 注意:在C++中会把运算符当作函数处理,使用运算符时会调用运算函数

    Test t1,t2,t3;     //无参构造
    t3 = t1 = t2;       //赋值操作函数
    
    类名& operator=(const 类名& that)
    {
        ···
    }
    
  • 什么时候需要显式地写赋值操作?
    普通情况一般不需要
    类似于需要显示地写拷贝构造一样,当需要进行深拷贝时,就需要显式地写拷贝构造和赋值操作

  • 实现赋值操作需要注意的问题:
    虽然赋值操作与拷贝构造的任务相同,都需要深拷贝,但是环境不同(旧对象、新对象)
    问题1:被赋值的对象的指针已经分配有内存

    a.先释放被赋值者的指针指向的原内存
    b.根据赋值者的赋值重新申请新内存
    c.把赋值者内存的内容深拷贝到新内存中
    

    问题2:可能会出现对象自己给自己赋值的情况

    通过判断this指针与赋值者的地址是否相同,如果相同立即返回*this结束,如果不相同才进行赋值操作
    
  • 笔试题:实现一个类似string的类 String的四个成员函数

class String
{
    char* num;
public:
    String(void)
    {
        num = new char;
    }
    String(const char* num)
    {
        int len = strlen(num);
        this->num = new char[len+1];
        strcpy(this->num,num);
    //    cout << "构造函数" << num << endl;
    }
    ~String(void)
    {
        delete[] num;
    //    cout << "析构函数" << num << endl;
    }
    String(const String& that)
    {
        int len = strlen(that.num);
        num = new char[len+1];
        strcpy(num,that.num);
    //    cout << "拷贝构造" << num << endl;
    }
    String& operator=(const String& that)
    {
        if(&that != this)
        {
            delete[] num;
            int len = strlen(that.num);
            num = new char[len+1];
            strcpy(num,that.num);
    //    cout << "赋值操作" << num << endl;
        }
        return *this;
    }
    void show(void)const
    {
        cout << num << endl;
    }
};

标签:函数,对象,成员,拷贝,指针,赋值
From: https://www.cnblogs.com/wangqiuji/p/17652717.html

相关文章

  • openGauss学习笔记-48 openGauss 高级数据管理-函数
    openGauss学习笔记-48openGauss高级数据管理-函数openGauss常用的函数如下:48.1数学函数abs(x)描述:绝对值。返回值类型:和输入相同。示例:openGauss=#SELECTabs(-17.4);abs------17.4(1row)cbrt(dp)描述:立方根。返回值类型:doubleprecision示例:openGauss......
  • c语言的可重入和不可重入函数
    先贴上一篇优秀的博文链接:C语言之可重入函数和不可重入函数_c可重入函数_KiranWang的博客-CSDN博客  总结:不可重入函数的四种情况1.静态数据结构:如静态局部变量活全局变量2.malloc()或者free()函数因为这两个函数都会操作全局的链表,如果第一次malloc没结束时,再被一次malloc......
  • 无涯教程-PHP Mock Test函数
    本节介绍了与PHP相关的各种模拟测试。您可以在本地计算机上下载这些样本模拟测试,并在方便时离线解决。每个模拟测试均随附一个模拟测试键,可让您验证最终分数并为自己评分。MockTestIMockTestIIMockTestIIIMockTestIVQ1-关于PHP,以下哪项是正确的?A-PHP是......
  • memmove函数
    参考引入问题intmain(){intarr1[10]={1,2,3,4,5,6,7,8,9,10};my_memcpy(arr1+2,arr1,20);for(inti=0;i<10;i++){printf("%d",arr1[i]);}return0;}上面一段代码我们的目的是想把到5的数字共20个字节拷贝到原来3到7的数字的位置上。然后我们看到其......
  • isEmpty工具函数
    在**项目开发中,需要在对未知数据类型做判空处理,期待空值列表:undefined、null、''、NaN、[]、{},注意非空:0、false;而常见的lodash.isEmpty,!value均不能直接满足我们的需求,那么我们需要抽离一个工具函数isEmpty; 接口返回表格字段的数据:表格中使用switch:0(或者false)......
  • 无涯教程-PHP Online Test函数
    该PHP在线测试模拟了真正的在线认证考试。您将看到基于PHP概念的多项选择题(MCQ),将为您提供四个options。您将为该问题选择最合适的答案,然后继续进行下一个问题,而不会浪费时间。完成完整的考试后,您将获得在线考试分数。总问题数-20最长时间-20分钟StartTest参......
  • fstat函数
    功能由文件描述符获取文件的状态头文件#include<sys/stat.h>#include<unistd.h>函数声明intfstat(intfiledes,struct*buf);两个参数分别为:intfiledes:已经打开的文件描述符,通常由open函数返回struct*buf:用来存放fstat所获取的文件的状态。fstat()用来将......
  • fprintf()函数
    fprintf()用于文件操作#include<stdio.h>intfprintf(FILE*stream,constchar*format,...);fprintf()函数根据指定的format(格式)发送信息(参数)到由stream(流)指定的文件.因此fprintf()可以使得信息输出到指定的文件.比如charname[20]="Mary";FILE*out;out=f......
  • 【C语言基础语法】5. 函数
    一、函数概述1.1函数的作用函数的使用可以省去重复代码的编写,降低代码重复率函数可以让程序更加模块化,从而有利于程序的阅读,修改完善1.2函数的调用:产生随机数调用函数时,需要关心:头文件:包含指定的头文件函数名字:函数名字必须和头文件声明的名字一样功能:需要知道此函数作用后才能调......
  • 无涯教程-PHP Online Quiz函数
    以下测验提供与PHP相关的多项选择题(MCQ)。您将必须阅读所有给定的答案,然后单击正确的答案。如果您不确定答案,则可以使用显示答案按钮检查答案。您可以使用下一个测验按钮检查测验中的新问题集。Q1-关于PHP,以下哪项是正确的?A-PHP可以访问cookie变量并设置cookie。......