深入C++03:面向对象

📕面向对象

类和对象、this指针

不用做太多笔记,都可以看初识C++的笔记;

记住👀:声明后面都要加” ;“,比如声明方法和变量还有class结束的地方;而实现函数出来的地方是不需要加” ;

为什么要按最大字节对齐?和内存池相关

掌握构造函数和析构函数

看初始C++笔记enough;

掌握对象得深拷贝和浅拷贝

浅拷贝:直接内存数据拷贝

SeqStack s;//默认构造函数;
SeqStack s2 = s;//调用拷贝构造函数;
SeqStack s3(s);//上下都是调用拷贝构造函数,类会有默认拷贝函数,如默认构造函数相同,不写会自己生成;
//(什么时候调用什么函数查看下面代码实践);

深入C++03:面向对象

容易错点:类对象含有对象内存之外的资源,比如说在堆中有内存资源,那么调用析构函数会发生错误;

深入C++03:面向对象

深拷贝: 自定义拷贝构造函数和重载=运算符

深拷贝原型例子:

深入C++03:面向对象

问题一:为什么C++面向对象里面拷贝数据的时候用for循环,不用 memcpy(ptmp, _pstack, sizeof(int)* _size)或者 relloc()?

因为memcpy和relloc都是浅拷贝,如果数据只是int、float这种简单类型,不会用到外部资源就没有什么问题,还是可以用这两个函数拷贝数据的,但是如果数据内是对象,对象内有指向外部内存,那么就会有浅拷贝的问题出现(delete了可以放弃的数据,会发现转移的数据也被释放了)。

深入C++03:面向对象

问题二:直接赋值不是浅拷贝操作吗?采用直接赋值操作怎么实现深拷贝呢?

一开始说两者 SeqStack s2 = s; SeqStack s3(s);都是有默认拷贝函数和默认的赋值函数,两个效果是相同的,都是直接拷贝内存数据;

void operator=(const SeqStack &src) {
    _pstack =  src._pstack;
    _top = src._top;
    _size = src._size;
}
//这个默认赋值函数还有一个问题:假设s, s2都初始化,这时候将s2 = s, s2中_pstack指向的内存(在构造函数时申请的空间)会没有指针指到,因为s2中的_pstack指向了  s中_pstack指向的空间(因为是浅拷贝啊!)
//所以我们重载赋值函数时要注意这个问题!

所以, 赋值函数=我们需要运算符重载

实例:

void operator=(const SeqStack &src) {
    //防止自赋值,自赋值如果不防止会出现内存访问异常,自己分析一下即可;
    if (this == &src) return;

    //需要先释放当前对象占用的外部资源
    delete []_pstack;

    //进行拷贝,和拷贝构造一样的操作
    _psatck = new int[src.size];
    for (int i = 0; i

浅拷贝有问题的时候再考虑深拷贝;

类和对象代码应用实践

①简写实现String类

#include
#include

using namespace std;

class String {
public:
    String(const char * str = nullptr) {//构造函数
        if (str != nullptr) {
            m_data = new char[strlen(str) + 1];//strlen函数不会读取'\0';
            strcpy(this->m_data, str);
            cout << "调用有参数的构造函数" << endl;
        }
        else {
            m_data = new char[1];  //这样不管为不为空,strlen都可以访问
            *m_data = '\0';
            cout << "调用没有参数的构造函数" << endl;
        }
    }
    ~String() {//析构函数
        delete m_data;
        m_data = nullptr;
    }
    String(const String &other) { //拷贝函数
        m_data = new char[strlen(other.m_data) + 1];
        strcpy(m_data, other.m_data);
        cout << "调用拷贝函数" << endl;
    }
    String& operator=(const String &other) {//=运算符重载,String& 是为了支持连续使用=
        if (this == &other) return *this;//注意,这里不能返回other,因为other有const修饰
        cout << "调用=赋值函数" << endl;
        delete m_data;
        m_data = new char[strlen(other.m_data) + 1];

        strcpy(m_data, other.m_data);
        return *this;
    }

private:
    char *m_data; //保存字符,要用深拷贝
    void resize() {

    }
};
int main () {
    //调用带const char*参数的构造函数;
    String str1;
    String str2("hello");
    String str3 = "world"; //一定条件下成立,刚刚好, 问题:为什么这个也可以调用构造函数?编译器优化相关
    String *test = new String("lulu");

    //调用拷贝构造函数
    String str4 = str3;
    String str5(str3);

    //调用赋值重载函数
    str1 = str2; //必须已经声明
    return 0;
}

深入C++03:面向对象

看看字符数组的操作

②循环队列

#include

using namespace std;

class Queue {
public:
    Queue(int size = 15) { //构造函数
        _pQue = new int[size];
        _front = _rear = 0;
        _size = size;
    }
    ~Queue() { //析构函数
        delete []_pQue;
        _pQue = nullptr;
    }
    void push(int val) {
        if (full()) resize();
        _pQue[_rear] = val;
        _rear = (_rear + 1) % _size;
    }
    void pop() {
        if (empty()) return;
        _front = (_front + 1) % _size;
    }
    int front() {
        if (empty()) return -1;
        return _pQue[_front];
    }
    bool empty() {
        return _front == _rear;
    }
    bool full() {
        return (_rear + 1) % _size == _front;
    }
    // Queue(const Queue &que) = delete; //不允许使用拷贝构造函数;
    Queue(const Queue &que) { //拷贝构造函数
        _front = que._front;
        _rear = que._rear;
        _size = que._size;
         _pQue = new int[_size];
        // for (int i = 0; i < _size; i++ ) {//这样写有些值不存在,而且浪费时间,遍历到了不用的值
        //     _pQue[i] = que._pQue[i];
        // }
        for (int i = _front; i != _rear; i = (i + 1) % _size) { //rear在的值是空的
            _pQue[i] = que._pQue[i];
        }
    }
    // Queue& operator=(const Queue &que) = delete; //不允许使用拷贝构造函数;
    Queue& operator=(const Queue &que) { //赋值函数
        if (this == &que) return *this;

        delete []this->_pQue;

        _front = que._front;
        _rear = que._rear;
        _size = que._size;
         _pQue = new int[_size];
        for (int i = _front; i != _rear; i = (i + 1) % _size) { //raer在的值是空的
            _pQue[i] = que._pQue[i];
        }
        return *this;
    }
private:
    int *_pQue; //队列的数组空间, 存在堆空间,类对象外空间,需要深拷贝
    int _front; //队头位置
    int _rear; //队尾位置
    int _size; //队列扩容总大小;
    void resize() { //扩容函数,注意实现
        int *newQue = new int[_size * 2];
        int index = 0;
        for (int i = _front; i != _rear; i = (i + 1) % _size) {
            newQue[index++] = _pQue[i];
        }
        delete []_pQue;
        _pQue = newQue;
        _front = 0;
        _rear = index;
        _size *= 2;
    }
};
int main() {
    Queue que;
    for (int i = 0; i < 20; i++) {
        que.push(i);
    }
    while(!que.empty()) {
        cout << que.front() << " ";
        que.pop();
    }
    return 0;
}

深入C++03:面向对象

掌握构造函数得初始化列表

①初始化列表和和构造函数函数体内写有什么区别?

可以去看看汇编代码

深入C++03:面向对象

②初始化列表的顺序是以类中成员变量的声明顺序去初始化的,而不是在初始化列表中出现的顺序!

深入C++03:面向对象

掌握类得各种成员方法以及区别

const、static、以及什么都不加,他们修饰的方法很花里胡哨,但是实际上就是this指针的区别;

深入C++03:面向对象

三者成员函数的实例:

深入C++03:面向对象

指向类成员的指针

直接看实例:

#include
#include

class Test {
public:
    void fun() {std::cout << "call Test::fun" << std::endl;};
    static void static_fun() {std::cout << "call Test::static_fun" << std::endl;};

    int ma;
    static int mb;
};
int main() {
    Test t1;
    Test *t2 = new Test();
    //操作普通成员变量,必须要①声明有Test作用域的指针,②有对象
    int Test::*p = &Test::ma;
    t1.*p = 20;//改变了t1中ma的值
    t2->*p = 20;//改变了t2中ma的值;
    //操作静态成员变量,直接用同类型指针操作即可
    int *p1 = &Test::mb;
    *p1 = 40;//改变了静态成员变量mb的值;

    //操作普通成员函数,必须要①声明有Test作用域的指针,②有对象
    void (Test::*pfun)() = &Test::fun;
    (t1.*pfun)();
    (t2->*pfun)();
    //操作静态成员函数,直接用同类型的指针即可
    void (*pstatic_fun)() = &Test::static_fun;

    return 0;
}

Original: https://www.cnblogs.com/D-booker/p/16347729.html
Author: D-booker
Title: 深入C++03:面向对象

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/715037/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • [转帖]通过使用telegraf+influx+grafana监控VMware虚拟化平台

    404. 抱歉,您访问的资源不存在。 可能是网址有误,或者对应的内容被删除,或者处于私有状态。 代码改变世界,联系邮箱 contact@cnblogs.com 园子的商业化努力-困…

    技术杂谈 2023年5月30日
    0118
  • 心态崩了,我怎么知道实际生产环境的 B+ 树索引有多少层?

    Q:在实际生产环境中,InnoDB 中一棵 B+ 树索引一般有多少层?可以存放多少行数据? 关于这个问题最近好像在牛客上经常看到,感觉没啥意义,可能主要考察的是对 B+ 索引的理解…

    技术杂谈 2023年7月25日
    0116
  • html大文件传输问题

    随着视频网站和大数据应用的普及,特别是高清视频和4K视频应用的到来,超大文件上传已经成为了日常的基础应用需求。 但是在很多情况下,平台运营方并没有大文件上传和断点续传的开发经验,往…

    技术杂谈 2023年5月30日
    099
  • java反序列化cc_link_one2

    前言 这条链子其实是上一条链子的另一种走法,在调用危险函数哪里是没有什么变化的 整体链子 还是尾部没有变化嘛还是InvokerTransformer的transform方法可以执行…

    技术杂谈 2023年6月21日
    0136
  • JAVA基本类型和包装类型

    JAVA基本类型和包装类型 前言 Java语言中的数据类型分为基本数据类型和引用类型,而我们进行Java开发的时候都听说过基本数据类型和包装类型,今天我们就来详细聊一聊Java中的…

    技术杂谈 2023年6月21日
    0108
  • PgSQL-to_char-保留小数位、格式时间格式

    to_char 1.保留小数 格式必须是9。小数点位数前保留位数不足则####;to_char中的第二个参数的小数点后面位数高于第一个参数,会用0补齐;to_char中的第二个参数…

    技术杂谈 2023年6月21日
    099
  • 【JVM】3、jvm参数和main方法参数

    在实际应用中,我们经常会使用一些额外的参数定义不通的环境下jvm的启动设置 特别是springCloud的项目,因为yml配置文件的问题,如果我们要做负载的话,会同时启动一个jar…

    技术杂谈 2023年7月24日
    074
  • Git rebase 合并多次提交

    在一般研发管理流程中,我们一般都是这么使用Git版本的: 0、先拿到一个需求(不细谈需求前面的采集、归纳整理、确认及评审等环节) 1、从主分支checkout一个新分支 2、在完成…

    技术杂谈 2023年7月11日
    0101
  • 命名实体识别是什么

    命名实体识别(Named Entity Recoginition, NER)旨在将一串文本中的实体识别出来,并标注出它所指代的类型,比如人名、地名等等。具体地,根据MUC会议规定,…

    技术杂谈 2023年7月11日
    0181
  • 8 月份全球 Wi-Fi6 技术标准更新

    1.巴林 TRA 启用 Wi-Fi6 2022 年 8 月 17 日,巴林电信管理局 (TRA) 批准了 5470-5725 MHz 和 5925-6425 MHz 频段用于 Wi…

    技术杂谈 2023年6月21日
    071
  • 【转】Xcode插件管理工具Alcatraz

    Original: https://www.cnblogs.com/wi100sh/p/13093966.htmlAuthor: wi100shTitle: 【转】Xcode插件管…

    技术杂谈 2023年6月1日
    096
  • 看了同事写的代码,我竟然开始默默的模仿了。。。

    事情是这样的,目前我正在参与 XXXX 项目的搭建,需要与第三方对接接口。在对方的接口中存在几个异步通知,为了接口的安全性,需要对接口的参数进行验签处理。 为了方便大家对异步通知返…

    技术杂谈 2023年7月11日
    0103
  • MySQL建表语句生成Golang代码

    1. 背景 对于后台开发新的需求时,一般会先进行各种表的设计,写各个表的建表语句 然后根据建立的表,写对应的model代码、基础的增删改查代码(基础的增删改查服务可以划入DAO(D…

    技术杂谈 2023年6月21日
    0134
  • Python中的异常(Exception)

    以下 Python 版本为 Python 3.8.10 . 初探异常 错误: 语法错误 . 逻辑错误 . 异常:程序运行过程中,出现的意料之外的错误(大概类似 corner cas…

    技术杂谈 2023年7月24日
    093
  • PHP自定义日期英文格式Feb11,2015

    背景:[PHP小工具]项目中,经常会要求多版本语言支持,而日期也是必不可少的组成元素。 英文日期书写顺序分英式和美式,举例如。 美国:月日年(January 8th,2014 或 …

    技术杂谈 2023年7月24日
    0107
  • CentOS-Docker部署collabora office实现文档在线浏览

    0 关于Collabora Online 实现网页中文档在线浏览和操作Collabora Online官方文档:https://www.collaboraoffice.com/co…

    技术杂谈 2023年6月21日
    0115
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球