博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C++ Primer Plus 学习笔记 第十八章 移动语义和右值引用, 默认构造函数和禁用函数, 委托和继承构造函数,override和final
阅读量:4126 次
发布时间:2019-05-25

本文共 4152 字,大约阅读时间需要 13 分钟。

移动语义:

简单地说就是 复制对象或者其他数据的时候 不再是通过创建临时对象,复制构造函数,创建新的对象,删除构造函数这样的方法了

而是将需要新对象的地方(变量)直接指向该数据,而数据本身不做任何移动或者改变。 这需要配合右值引用的使用才可以达到此目的

程序例子

#include 
using namespace std;class Useless{ private: int n; char* pc; static int ct; void ShowObject() const; public: Useless(); explicit Useless(int k); Useless(int k, char ch); Useless(const Useless & f); Useless(Useless && f); ~Useless(); Useless operator+(const Useless & f) const; void ShowData() const;};int Useless:: ct = 0;Useless::Useless(){ ++ct; n = 0; pc = nullptr; cout << "default constructor called; number of objects: " << ct << endl; ShowObject();}Useless::Useless(int k) : n(k){ ++ct; cout <<"int constructor called; number of objects: " << ct << endl; pc = new char[n]; ShowObject();}Useless::Useless(int k, char ch) : n(k){ ++ct; cout << "int, char constructor called; number of objects: " << ct << endl; pc = new char[n]; for (int i = 0; i < n; i++) pc[i] = ch; ShowObject();}Useless::Useless(const Useless & f): n(f.n){ ++ct; cout << "copy const called; number of objects: " << ct << endl; pc = new char[n]; for(int i = 0; i < n; i++) pc[i] = f.pc[i]; ShowObject();}// 这里是移动构造函数Useless::Useless(Useless && f): n(f.n){ ++ct; cout << "monve constructor called; number of objects: " << ct << endl; pc = f.pc; f.pc = nullptr; f.n = 0; ShowObject();}Useless::~Useless(){ cout << "destructor called; objects left: " << --ct << endl; cout << "deleted object:\n"; ShowObject(); delete [] pc;}Useless Useless::operator+(const Useless & f) const{ cout << "Entering operator+()\n"; Useless temp = Useless(n + f.n); for(int i = 0; i < n; i++) temp.pc[i] = pc[i]; for(int i = 0; i < temp.n; i++) temp.pc[i] = f.pc[i - n]; cout << "temp object:\n"; cout << "Leaving operator+()\n"; return temp;}void Useless::ShowObject() const{ cout << "Number of elements: " << n; cout << " Data address: " << (void *) pc << endl;}void Useless::ShowData() const{ if ( n == 0) cout << "(object empty)"; else for(int i = 0; i < n; i++) cout << pc[i]; cout << endl;}int main(){ Useless one(10, 'X'); Useless two = one; Useless three(20, 'o');// 在调用operator+后返回临时对象的时候会调用// 但不是每个编译器都调用,反正我这里没效果。最后依然用了复制构造函数 Useless four (one + three); cout << "object one: "; one.ShowData(); cout << "object two: "; two.ShowData(); cout << "object three: "; three.ShowData(); cout << "object four: "; four.ShowData();}

我的编译器没出来 嗯。。。突然不想理这个移动构造函数了

移动构造函数可以用在operator=函数中

强行移动

可以使用static_cast<>将对象强行转换成右值 

c++11有更简单的方法 <utility>下有个 std::move()函数

 

程序示例

#include 
//使用move()函数时需要的头文件#include
class Useless{ private: int n; char* pc; static int ct; void ShowObject() const; public: Useless(); explicit Useless(int k); Useless(int k, char ch); Useless(const Useless & f); Useless(Useless &&f); ~Useless(); Useless operator+(const Useless & f) const;// 不同时候调用不懂的operator= Useless & operator=(const Useless & f); Useless & operator=(Useless && f); void ShowData() const;};int Useless::ct = 0;Useless::Useless(){ ++ct; n = 0; pc = nullptr;}Useless::Useless(int k) : n(k){ ++ct; pc = new char[n];}Useless::Useless(int k, char ch) : n(k){ ++ct; pc = new char[n]; for(int i=0; i

如果没有提供移动构造函数的话,编译器会提供一个默认的

也会提供一个默认的移动运算符

默认的方法和禁用的方法

想要显示的指定某个构造函数,赋值构造函数和赋值构造函数等构造函数为默认方法

只需要在函数后面加上“ = default”

Someclass(const Someclass &) = default;

同样 如果要禁止编译器使用特定的方法的话 将‘default’改成“delete”

这个跟 ‘将复制构造函数和赋值运算符放到private部分’的效果一样

default只能用于6种特殊函数 delete全适用

比如:

class Someclass{public:    void redo(double);};.....Someclass sc;sc.redo(5);// 这时候会将5提升为5.0调用redo()//但是改成如下class Someclass(){public:    void redo(double);    void redo(int) = delete;};//再使用sc.redo(5)则会报编译错误

 

委托构造函数:

在一个构造函数中调用另一个构造函数,实现代码复用。 

这个可以算偷懒么(手动斜眼笑)

 

继承构造函数

c++98中允许利用命名空间的方式实现继承类调用父类函数

c++11将这种方法用于构造函数中(不包括默认构造函数,复制构造函数和移动构造函数已经与派生类构造函数特征标匹配的构造函数)

示例: 该例子也用了委托构造函数

 

管理虚函数

override: 用来声明要覆盖一个父类的虚函数

父类: 

virtual void f(char ch) const {......} const

子类

virtual void f(char* ch){........} const override

因为子类与父类的虚函数在特征标上不匹配 所以编译器会直接报错 

final: 用来标识某个虚函数禁止派生类覆盖

virtual void f(char ch) const final {...};

你们两打一架吧

完结

转载地址:http://osepi.baihongyu.com/

你可能感兴趣的文章
Piper Sandler为EverArc收购Perimeter Solutions提供咨询服务
查看>>
RMRK筹集600万美元,用于在Polkadot上建立先进的NFT系统标准
查看>>
JavaSE_day14 集合中的Map集合_键值映射关系
查看>>
异常 Java学习Day_15
查看>>
Mysql初始化的命令
查看>>
MySQL关键字的些许问题
查看>>
浅谈HTML
查看>>
css基础
查看>>
Servlet进阶和JSP基础
查看>>
servlet中的cookie和session
查看>>
过滤器及JSP九大隐式对象
查看>>
软件(项目)的分层
查看>>
菜单树
查看>>
Servlet的生命周期
查看>>
JAVA八大经典书籍,你看过几本?
查看>>
《读书笔记》—–书单推荐
查看>>
JAVA数据类型
查看>>
【Python】学习笔记——-6.2、使用第三方模块
查看>>
【Python】学习笔记——-7.0、面向对象编程
查看>>
【Python】学习笔记——-7.2、访问限制
查看>>