当前位置: 首页 > news >正文

C++面向对象 Part 2

文章目录

    • 类六个默认存在的成员函数
      • 构造函数:
      • 析构函数:
      • 拷贝构造函数:
        • 拷贝构造详解及细节:
      • 赋值运算符重载;
      • 取地址及const取地址操作符重载
      • const修饰的含义:

类六个默认存在的成员函数

  • 构造函数

  • 析构函数

  • 拷贝构造函数

  • 赋值运算符重载

  • const成员函数

  • 取地址及const取地址操作符重载

    **一个类中,不管存不存在成员变量和成员函数,其内部都会默认生成以上六个成员函数 **

    构造函数:

    在一个类中,如果没有自定义任何构造函数,会自动生成一个默认的无参构造函数,其没有任何功能。如果自己定义过一次构造函数,则不会生成默认构造函数,如果我们定义的不是无参构造方法,以后就不可再使用无参构造了,当然我们可以在定义出来一个无参构造函数。构造函数的格式: 类名(参数列表){操作}…

构造函数还有个点,就是当一个类包含另一个类的时候,默认构造函数会默认调用被包含类的默认构造函数

析构函数:

析构函数的作用和构造函数是相反的,构造函数的作用是初始化类成员变量,析构函数的作用就是当对象使用完了以后,需要销毁的时候对内部的数据结构进行释放操作 格式: ~类名(){成员变量释放操作}

举个例子:数组栈的C++实现方法

//File:Stack.h
#include<iostream>
using namespace std;
class Stack {
private:int* arr;int capcity;int top;bool CheckMemory();
public:Stack();~Stack();Stack(const Stack& s);void PushBack(int n);int TopStack();void PopStack();bool isEmpty();
};//File:Stack.cpp
#include"Stack.h"
Stack::Stack() {capcity = 4;top = -1;int* temp = (int*)malloc(sizeof(int) * capcity);if (temp == nullptr) {perror("malloc fail");exit(-1);}arr = temp;
}
Stack::~Stack(){free(arr);capcity=top = 0;
}
Stack::Stack(const Stack& s) {this->capcity = s.capcity;this->top = s.top;//deepin copyint* temp = (int*)malloc(sizeof(int) * s.capcity);if (temp == nullptr) {perror("copy fail");exit(-1);}this->arr = temp;memcpy(arr, s.arr, sizeof(int) * capcity);
}
void Stack::PushBack(int n) {if (CheckMemory()) {//扩容int* temp=(int*)realloc(arr, sizeof(int) * capcity * 2);if (temp == nullptr) {perror("realloc fail");exit(-1);}arr = temp;capcity *= 2;}arr[++top] = n;
}
int Stack::TopStack() {return arr[top];
}
void Stack::PopStack() {top--;
}
bool Stack::CheckMemory() {return top == capcity - 1;//ture is full,false isn't full
}
bool Stack::isEmpty(){return top == -1;
}

拷贝构造函数:

拷贝构造就有意思了,在开始讲解之前我先用一段代码提问下大家:

class demo {
private:int _a;
public:demo() {_a = 1;cout << "demo()" << endl;}~demo(){cout << "~demo()" << endl;}demo(const demo& d) {_a = d._a;cout << "demo(const demo& d)" << endl;}
};
int main() {demo d1;demo d2=d1;return 0;
}

我想问下大家:这个main函数里的d2=d1 是进行的赋值操作还是进行的拷贝构造的操作?

答案:

在这里插入图片描述

显然这里进行的是拷贝复制,这里我们将讲解下这是怎么回事,以及为什么这里的拷贝构造函数为什么要传引用变量

拷贝构造详解及细节:

1. 首先由C++的规定,我们在对一个并未初始化的类进行值传递的时候,调用的就是拷贝构造函数,而不是赋值函数,这就很简单的解决了这里为什么调用的是拷贝构造函数的问题。

**2.第二个令人感到困惑的点就是,拷贝构造函数我们传递的是引用数据类型,首先也有个硬性规定,这里传递的必须是指针,另外这也是为了和第一点的特性做自洽处理,因为我们如果值传递话,会陷入一种无穷递归的情况,每次传值都会进行一次拷贝调用,每次拷贝调用,也会触发值传递。这里没有任何方法可以控制,因为这个递归他不会进入到函数每部,除非栈空间耗尽,不然他会一直递归 **

3. 拷贝构造在遇到成员变量也是一个类的时候,也会调用被包含类的默认构造函数进行拷贝操作

4. 深浅拷贝问题,其实我们大多数时候默认的拷贝构造,只会完成浅拷贝,这就会导致一个问题,两个类的指针成员函数都指向一块堆空间,这样在对象的生命周期结束时候,进行销毁操作在析构函数里会对一片地址重复释放,这样会直接引起程序的崩溃

赋值运算符重载;

其实赋值运算符重载的注意事项和拷贝构造函数的注意点最重要的就是深浅拷贝的问题,不同的情况要灵活运用,还有一个重要的就是赋值操作运算符重载只能在类的内部进行定义,不能定义为全局函数,其实这也很好理解,因为如果我们不在类内定义的话,编译器会自动生成一个默认的赋值函数,这样会与全局的赋值运算符重载冲突。

取地址及const取地址操作符重载

其余两个默认成员函数其实并不怎么重要了,这里我也就不做过多的赘述,下边我需要讲一些重要的概念

demo* operator&(){return this;
}const demo* operator&()const
{
return this ;
}

const修饰的含义:

eg:

const int& a=1;
int& b=1;
const int& c=a+2;
int& d=a+2;

请各位判断上边代码的对错情况:

答案:√×√×

这是为什么呢?

主要是因为上述代码的右值都是临时变量,而临时变量都具有常性,而引用临时变量稍有不慎就会造成权限的放大,大家自己想一下,定义出来的a是存在栈上的还是在常量区。

http://www.lryc.cn/news/297631.html

相关文章:

  • 海外云手机的核心优势
  • CDN相关和HTTP代理
  • STM32的ADC电压采集
  • 基于麻雀优化算法优化XGBoost参数的优化控制策略
  • Python爬虫——请求库安装
  • 瑞芯微推理RKNN使用
  • 动漫风博客介绍页面源码
  • 网络的基本概念和socket编程
  • 探索C语言的内存魔法:动态内存管理解析
  • 2023年全国职业院校技能大赛软件测试赛题第3套
  • 【数据分享】1929-2023年全球站点的逐日降水量数据(Shp\Excel\免费获取)
  • SpringBoot WebSocket客户端与服务端一对一收发信息
  • MinGW/MSYS/GCC/GNU/MSVC/Clang/LLVM都是什么
  • 9.0 Zookeeper 节点特性
  • VUEX项目场景
  • vue+springboot前后端视频文件等的上传与展示(基于七牛云)
  • ClickHouse--02--安装
  • 【学网攻】 第(23)节 -- PPP协议
  • Rust方法自动解引用测试,总结和补充
  • 备战蓝桥杯---动态规划之经典背包问题
  • Go语言每日一练——链表篇(八)
  • 跟着cherno手搓游戏引擎【23】项目维护、2D引擎之前的一些准备
  • Redis(十三)缓存双写一致性策略
  • 7 scala的类构造器
  • 如何在 Mac 上恢复永久删除的文件:有效方法
  • Web后端开发:事务与AOP
  • [word] word如何打印背景和图片? #微信#其他#经验分享
  • Maven - 编译报错:程序包 XXX 不存在(多模块项目)
  • Vue事件中如何使用 event 对象
  • Golang GC 介绍