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

上海网站建设的公司成都高端网站建设哪家好

上海网站建设的公司,成都高端网站建设哪家好,做网站用lunx,牛什么网站建设上一篇我们讲了构造函数,就是对象实例化时会自动调用,那么,我们这里的拷贝构造在形式上是构造函数的一个重载,拷贝构造其实也是一种构造函数,那么我们就可以引出这里的规则 1.拷贝构造函数的函数名必须与类名相同。 2.…

上一篇我们讲了构造函数,就是对象实例化时会自动调用,那么,我们这里的拷贝构造在形式上是构造函数的一个重载,拷贝构造其实也是一种构造函数,那么我们就可以引出这里的规则

1.拷贝构造函数的函数名必须与类名相同。
2.拷贝构造函数的参数必须为一个引用(否则会引起无穷递归),通常是 const 类型的引用,用来指定被拷贝的对象。
3.拷贝构造函数用来初始化一个新的对象,新的对象与被拷贝的对象应该属于同一类。
4.如果不手动定义拷贝构造函数,那么编译器会自动生成一个默认的拷贝构造函数,该函数进行浅拷贝

其实一个日期的类进行浅拷贝就行了,只需要把值给复制过去;但是对于一个栈的话,因为有了自动调用析构函数这个特性,那么我们就不能只去浅拷贝,而是把栈在堆上申请的空间包括值都要去拷贝一份(这里就是指拷贝指针背后的资源),这里也就是我们所说的深拷贝
我们看一下第四条规则,它是会生成一个默认的拷贝构造函数的,对于内置类型是这样的
在这里插入图片描述
当然对于自定义类型来说会去调用它的拷贝构造函数
根据第一二条规则我们可以看出拷贝构造函数的基本形式是这样的
拷贝构造函数
当然了,根据第四条,我们其实不写日期类的拷贝构造函数的话编译器是会默认生成的。这个拷贝构造函数其实在栈这一些类中才是有价值的
我们看下面这样一个例子

class stack {
public:stack(int capacity=3) {cout << "stack" << endl;int* tmp = (int*)malloc(sizeof(int) * capacity);if (tmp == nullptr) {perror("malloc failed");return;}_a = tmp;_top = 0;_capacity = capacity;}~stack(){cout << "~stack" << endl;free(_a);_a = nullptr;_top = 0;_capacity = 0;}
private:int* _a;int _top;int _capacity;
};
void func(stack x) {cout << "func" << endl;
}
int main() {stack s1;func(s1);return 0;
}

这个代码其实是会报错的,因为s1传给x时是要调用一次拷贝构造的(因为我们一直说形参是实参的一份临时拷贝),而我们没有写拷贝构造函数,那么此时编译器就会默认进行浅拷贝,也就是把s1的_a指针的值去给了x,当要出x的作用域时,x就会调用它的析构函数,此时就释放了指针指向的空间,函数出来后要出s1的作用域时又要调用析构函数,这就导致一块空间被释放(free)了两回,这时就会报错,这也就解释了为什么开头我说跟析构函数有关
那么写上栈的拷贝构造函数就可以了

	stack(const stack& x) {int* tmp = (int*)malloc(sizeof(int) * _capacity);if (tmp == nullptr) {perror("malloc fail");exit(-1);}memcpy(tmp, x._a, sizeof(int) * x._top);_a = tmp;_top = x._top;_capacity = x._capacity;}

下边的赋值运算符重载也是类的默认成员函数中的一个,说这个之前,我们还是先解释一下什么叫运算符重载
我们平常在用运算符时(> + = >= 等),只能对于内置类型进行使用,对于自定义类型不能使用,因为编译器认识内置类型,它知道怎么去运行。但是对于自定义类型它也不知道怎么去操作。
这时呢?为了方便,我们就要去写一个类的函数(这里以==为例),我们写是会写,但是可能写的函数名可能会使别人不认识,这时,我们的C++祖师爷就制定了一个标准,函数名就是operator操作符
比如说,我们写一个日期类的比较相等的函数

bool operator==(const Date&d1,const Date& d2) {if (d1._year == d2._year && d1._month == d2._month && d1._day == d2._day) {return true;}return false;
}

但是有一个问题,就是我们的成员变量一般是私有的,也就是在类外是访问不了的,我们当然访问有很多种方式,但几乎都是用一个类里面的函数把值给弄出来,那我们还不如直接把运算符重载的函数放到类中,把它变成一个成员函数
那么此时,它的形式就会有所变化

#include<iostream>
using namespace std;
class Date {
public:Date(int year = 1, int month = 1,int day=1) {_year = year;_month = month;_day = day;}bool operator==( const Date& d) {if (_year == d._year && _month == d._month && _day == d._day) {return true;}return false;}
private:int _year;int _month;int _day;
};int main() {Date d1(2023, 3, 1);Date d2;int ret = d1.operator==(d2);cout << ret << endl;return 0;
}

这里的d1是利用构造函数去初始化了,d2没有传值就是去调用默认构造函数,实际上就是利用缺省值去进行初始化。调用成员函数就像主函数第三行一样,因为编译器会默认传一个this指针
既然我们都这么写了,那么我们能不能再简化一点呢?
其实我们可以直接用符号去比较

int main() {Date d1(2023, 3, 1);Date d2;int ret = d1 == d2;//int ret = d1.operator==(d2);cout << ret << endl;return 0;
}

这样写就会让编译器默认去调用下面的函数
有了运算符重载的知识,我们下面写一下赋值运算符重载,

	Date& operator=(const Date& d) {if (this != &d) {_year = d._year;_month = d._month;_day = d._day;}return *this;}

这里要注意如果=左右是一个对象的话是不需要去赋值的,并且用的是引用返回不需要拷贝,有返回值是因为有可能要连续赋值,就像下边

d1=d1;
d1=d2=d3;

赋值运算符重载函数和拷贝构造函数是一样的,对于内置类型会去调用默认的函数,对于自定义类型会去调用自定义类型定义好的函数

http://www.hengruixuexiao.com/news/8542.html

相关文章:

  • 如何做网站平台关注安装百度到桌面
  • 东平企业建站公司培训机构专业
  • 贵州建设网老网站搜索引擎优化
  • 门户子网站建设申请东莞企业网站设计公司
  • 深圳设计师品牌东莞seo黑帽培训
  • 网页设计和网站建设书百度seo简爱
  • 近日发生的重大新闻网络优化
  • wordpress 添加栏目百度seo网站优化
  • qq互联网站备案号友情链接属于免费推广吗
  • wordpress目录排序安卓优化大师清理
  • 合肥网站建设费用app运营方案
  • 网站制作报价单模板pc网站优化排名
  • 男的直接做的视频网站营销咨询公司经营范围
  • google移动网站建站十大原则成都门户网站建设
  • 动漫在线制作网站网站网络推广运营
  • 上海专业网站建老铁seo外链工具
  • 加强网站备案管理专项行动今日时政新闻
  • 做淘宝网店需要多少钱seo关键词优化报价
  • 网站建设基本内容教育培训机构排名
  • 建设什么网站可以上传视频营销手段和技巧
  • 上海浦东哪里有做网站的公司seo网络营销推广公司
  • 广告公司名称取名自贡网站seo
  • 沈阳网站建设专家工具站seo
  • 做网店在素材网站找的图侵权吗湖南网站设计外包哪家好
  • web网站设计的要求兰州网络推广推广机构
  • 网站的seo怎么做竞价排名
  • 浏览器怎么做能不拦截网站b2b网站平台有哪些
  • java做视频网站的需求合肥网络推广平台
  • 网站商城建设合同范本关键词推广优化app
  • 泰州网站制作网站软文范例大全100