C++类中隐藏的六个默认函数
Test类中隐藏的六个默认的函数
class Test
{
public:
//默认的构造函数
Test();
//析构函数
~Test();
//拷贝构造函数
Test(const Test &t);
//赋值函数
Test& operator=(const Test &x);
//一般对象取地址函数
Test* operator&();
//常对象取地址函数
const Test* operator&()const;
private:
int data;
//int *data;
};
1.构造函数
作用:对象所在的内存空间做初始化 、给对象赋资源
特点:
- 可以重载 :可以根据实际需要进行缺省的、多参重载
- 不依赖对象:对象无法调用构造函数,只能在对象定义点被调用
//成员函数类外实现,需在函数名前指定作用域,否则编译器会认为在定义一个普通的函数
Test::Test() //类中默认的构造函数
{
}
//此外,构造函数可以支持重载,我们可以根据需要自己写一些构造函数
//需要注意的是,如果我们自己写了构造函数,那么编译器就不会提供默认的构造函数了
Test::Test(int d = 0 ) //缺省的构造函数
{
data = d;
}
Test::Test(int d = 0 ):data(d) //缺省的构造函数,用初始化器的方式初始化
{
}
两者初始化的区别在于,初始化器是真正意义上的初始化,它告诉编译器在实例化对象的时候以何种方式对成员赋值,而在前者的赋值规则写在了构造函数内部,是在已经生成了成员变量之后再进行的赋值操作。
初始化器实例:比如以下操作,成员变量定义为const类型,在C语言中const类型是一个常变量在定义的时候可以不初始化,而在C++中规定const类型为一个常量,定义时必须初始化。所以以下操作只能使用初始化器的方式初始化。
class Test
{
public:
Test(int a)
:ma(a)
{
//ma = a;
}
private:
const int ma;
};
此外,如果有多个成员变量需要使用初始化器的方式初始化,需要注意一点细节,初始化的顺序与成员变量的定义顺序相关。如以下程序,可以写成Test(int a):ma(mb), mb(a){}或Test(int a):mb(a),ma(mb){}因为成员变量的定义顺序为int mb; int ma;,也就是说赋值顺序与初始化器无关,只与成员变量被定义的顺序有关。
class Test
{
public:
Test(int a):ma(mb), mb(a) //mb先被定义出来,先给mb赋值,再给ma赋值
{
}
Test(int a):mb(ma), ma(a) //error mb先定义出来,此时ma还未被定义,所以mb(ma)赋值无效,最终结果为,mb无效值,ma=a
{
}
void Show()
{
std::cout << "ma: " << ma << std::endl;
std::cout << "mb: " << mb << std::endl;
}
private:
int mb;
int ma;
};
2.析构函数
作用:释放对象所占的其他资源。
特点:
- 不可重载 : 对象销毁时会调用析构函数,并释放空间。
- 依赖对象:可用手动调用,但是不建议,因为对象销毁时会自动调用,如果手动调用可能会引起内存空间的重复析构导致程序崩溃
//默认的析构函数
Test::~Test()
{ //没有额外的资源,什么都不写
}
//如果程序中有额外的空间需要释放
class Test
{
public:
//构造函数
Test()
{
data = new int; //data指向一块堆区内存
}
//析构函数
~Test();
private:
int* data;
};
//析构函数
Test::~Test()
{
delete data; //把额外空间的释放写进析构函数
}
3.拷贝构造函数
作用:拿一个已存在的对象来生成相同类型的新对象
注意:类中提供的拷贝构造函数为一个浅拷贝类型,即如果成员变量中含有指针类型,它在进行拷贝构造的时候不会进行额外空间的开辟,最终会造成函数析构时的错误。
class Test
{
public:
//构造函数
Test()
{
data = new int; //data指向一块堆区内存
}
//拷贝构造函数
Test(const Test &t); //一定要传引用,否则在开辟形参的过程中会递归的调用拷贝构造函数来构造形参,而函数始终无法执行
private:
int* data;
};
//默认的拷贝构造函数
Test::Test(const Test &t)
{
data = t.data; //浅拷贝,只把现有的成员变量进行拷贝,没有对堆区内存进行拷贝,使多个对象的data指向了同一片堆区空间,在对象销毁时会造成空间的重复释放引发程序崩溃。
}
//拷贝构造函数
Test::Test(const Test &t)
{
data = new int; //如果是字符类型data = new char[strlen(t.data) + 1];
strcpy_s(data,sizeof(int), t.data);
}
4.赋值运算符的重载函数
作用:拿一个已存在的对象给相同类型的已存在对象赋值
实现步骤
- 自赋值判断
- 释放旧资源
- 生成新资源
- 赋值
class Test
{
public:
//构造函数
Test()
{
data = new int; //data指向一块堆区内存
}
//赋值函数
Test& operator=(const Test &x); //以自身类类型的引用的方式返回
private:
int* data;
};
//默认的赋值函数(浅拷贝)
Test& operator=(const Test &x)
{
if(this!=&x) //自赋值判断
{
data=x.data; //浅拷贝
}
return *this; //返回自身类类型的引用
}
//赋值函数(深拷贝)
Test& operator=(const Test &x)
{
if(this!=&x) //自赋值判断
{
delete[] data; //释放原资源,比如 a = 4, b = 5, a = b此时a放弃原先的资源 4
data = new int;
strcpy_s(data,sizeof(int), t.data);
}
return *this; //返回自身类类型的引用
}
5.一般对象取地址函数
//一般对象取地址函数
Test::Test* operator&()
{
return this;
}
6.常对象取地址函数
//常对象取地址函数
const Test::Test* operator&()const
{
return this;
}
C++类中隐藏的六个默认函数的更多相关文章
- 孤荷凌寒自学python第二十四天python类中隐藏的私有方法探秘
孤荷凌寒自学python第二十四天python类中隐藏的私有方法探秘 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 今天发现了python的类中隐藏着一些特殊的私有方法. 这些私有方法不管我 ...
- C++11 类的六个默认函数及其使用
六个默认函数: 构造函数(construct) 析构函数(destruct) 复制构造函数(copy construct) 赋值(assign) 移动构造函数(move construct) 移动赋值 ...
- C++类中的静态成员变量与静态成员函数
最近一直看c++相关的项目,但总是会被c++类中的静态成员变量与静态成员函数的理解感觉很是模糊,不明白为什么类中要是用静态成员变量.于是在网上搜集了一些资料,自己再稍微总结下. 静态成员的概念: 静态 ...
- C++ 类中的静态成员变量,静态成员函数
//类中的静态成员变量,静态成员函数 #define _CRT_SECURE_NO_WARNINGS #include<iostream> using namespace std; /* ...
- C++类中的静态成员变量和静态成员函数的作用
数据成员可以分为静态变量.非静态变量两种. 静态成员:静态类中的成员加入static 修饰符,即是静态成员,可以使用类名+静态成员名访问此静态成员,因为静态成员存在于内存,非静态成员需要实例化才会分配 ...
- C++类中的静态成员变量与静态成员函数的使用
代码: #include <iostream> #include <string> #include <cstdio> using namespace std; c ...
- C# 类中隐藏基类方法和Partial
今天对于.NET开发人员来说最开心的事情莫过于微软搞开源了,这觉得是给搞.NET开发的长脸.虽然我是一个初学者,这无疑给我极大的学习动力.Fighting!!! 当一个类从父类继承了一个成员时,也就继 ...
- QWidget类中默认是忽略inputMethodEvent事件(要获取输入的内容就必须使用这个事件)
因为项目的需要以及主管的要求,准备将工程移植到Qt中,这样就可以比较容易的实现跨平台了.因为之前工程是在windows下开发的,第一个平台又是mobile所以除了底层框架之外其他的都是使用的windo ...
- C++类的默认函数
在C++中,一个类有八个默认函数: 默认构造函数: 默认拷贝构造函数: 默认析构函数: 默认重载赋值运算符函数: 默认重载取址运算符函数: 默认重载取址运算符const函数: 默认移动构造函数(C++ ...
随机推荐
- 一个C#程序的执行过程
可能很多人都知道我们把程序打包成dll就丢出去了,但是里面的具体的执行过程是怎么样的呢. 程序集是由元数据和IL组成的.IL是和CPU无关的语言,是微软的几个专家请教了外面的编译器的作则,开发出来的. ...
- 哈工大 计算机系统 大作业 程序人生-Hello’s P2P
计算机系统 大作业 题 目 程序人生-Hello's P2P 专 业 计算机 学 号 班 级 学 生 指 导 教 师 计算机科学与技术学院 2021年6月 摘 要 本文主要通过分析hello这个程序的 ...
- Qt:QList、QStringList
QList 0.说明 QList<T> 一个QList是存储相同类型一组数据的列表. QStringList是从QList<String>继承而来,并添加了一些好用的方法,如j ...
- 使用resize浏览器窗口大小改变事件容易出现的问题
1.使用jQuery的resize时间的时候发现每次改变浏览器窗口大小事resize事件会执行两次, 解决办法 var resizeTimer=null; $(window).resize(funct ...
- 用WebDev.WebServer40.EXE调试VS代码
1.找到WebDev.WebServer40的录井,一般位于C:/Program Files (x86)/Common Files/Microsoft Shared/DevServer/10.0/We ...
- 基于SqlSugar的数据库访问处理的封装,支持多数据库并使之适应于实际业务开发中
在我的各种开发框架中,数据访问有的基于微软企业库,有的基于EFCore的实体框架,两者各有其应用场景,不过多的去比较.最近在使用SqlSugar的时候,觉得这个数据访问处理的组件确实很灵活,据说性能也 ...
- 【有奖调研】来,聊聊TTS音色定制这件事儿
音色个性化定制,一个能让文字转语音服务(TTS)在用户交互过程中注入温度的技术. 文能在营销及内容交付中让品牌保持一致性,武能让开发者"音"量加持,创新开发. 这个100%钢铁纯技 ...
- 微服务入门三:SpringCloud Alibaba
一.什么是SpringCloud Alibaba 1.简介 1)简介 阿里云未分布式应用开发提供了一站式解决方案.它包含了开发分布式应用程序所需的所有组件,使您可以轻松地使用springcloud开发 ...
- 8.Flink实时项目之CEP计算访客跳出
1.访客跳出明细介绍 首先要识别哪些是跳出行为,要把这些跳出的访客最后一个访问的页面识别出来.那么就要抓住几个特征: 该页面是用户近期访问的第一个页面,这个可以通过该页面是否有上一个页面(last_p ...
- 基于ESP8266+BY8301语音模块的与山地车捉迷藏的小项目
基于ESP8266+BY8301语音模块的与山地车捉迷藏的小项目 写在前面: 不知道大家有没有经历过,在茫茫车海中找不到自己山地车情况,针对这个痛点(开玩笑的),我做了个小玩意,纯属娱乐,拿出来,在疫 ...