<C++> C++11 新的类功能

news/2025/1/11 5:01:56/

C++11 新的类功能

1.默认成员函数

原来C++类中,有6个默认成员函数:

  1. 构造函数
  2. 析构函数
  3. 拷贝构造函数
  4. 拷贝赋值重载
  5. 取地址重载
  6. const取地址重载

最后重要的是前4个,后两个用处不大。默认成员函数就是我们不写编译器会生成一个默认的。

C++11 新增了两个:移动构造函数和移动赋值运算符重载

针对移动构造函数移动赋值运算符重载有一些需要注意的点如下:

  • 如果你没有自己实现移动构造函数,且没有实现析构函数拷贝构造拷贝赋值重载中的任意一个。那么编译器会自动生成一个默认移动构造。默认生成的移动构造函数,对于内置类型成员会执行逐成员按字节拷贝自定义类型成员,则需要看这个成员是否实现移动构造, 如果实现了就调用移动构造没有实现就调用拷贝构造
  • 移动赋值重载同上规则相同
  • 如果你提供了移动构造或者移动赋值,编译器不会自动提供拷贝构造和拷贝赋值。

以下代码在vs2013中不能体现,在vs2019下才能演示体现上面的特性。

namespace phw {class string {public:typedef char *iterator;iterator begin() {return _str;}iterator end() {return _str + _size;}string(const char *str = ""): _size(strlen(str)), _capacity(_size) {//cout << "string(char* str)" << endl;_str = new char[_capacity + 1];strcpy(_str, str);}// s1.swap(s2)void swap(string &s) {::swap(_str, s._str);::swap(_size, s._size);::swap(_capacity, s._capacity);}// 拷贝构造string(const string &s): _str(nullptr) {cout << "string(const string& s) -- 深拷贝" << endl;string tmp(s._str);swap(tmp);}// 移动构造string(string &&s): _str(nullptr) {cout << "string(string&& s) -- 移动拷贝" << endl;swap(s);}// 赋值重载string &operator=(const string &s) {cout << "string& operator=(string s) -- 深拷贝" << endl;string tmp(s);swap(tmp);return *this;}// s1 = 将亡值string &operator=(string &&s) {cout << "string& operator=(string&& s) -- 移动赋值" << endl;swap(s);return *this;}~string() {//cout << "~string()" << endl;delete[] _str;_str = nullptr;}char &operator[](size_t pos) {return _str[pos];}void reserve(size_t n) {if (n > _capacity) {char *tmp = new char[n + 1];strcpy(tmp, _str);delete[] _str;_str = tmp;_capacity = n;}}void push_back(char ch) {if (_size >= _capacity) {size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;reserve(newcapacity);}_str[_size] = ch;++_size;_str[_size] = '\0';}//string operator+=(char ch)string &operator+=(char ch) {push_back(ch);return *this;}string operator+(char ch) {string tmp(*this);tmp += ch;return tmp;}const char *c_str() const {return _str;}private:char *_str;size_t _size;size_t _capacity;// 不包含最后做标识的\0};//const bit::string& to_string(int value)phw::string to_string(int value) {bool flag = true;if (value < 0) {flag = false;value = 0 - value;}phw::string str;while (value > 0) {int x = value % 10;value /= 10;str += ('0' + x);}if (flag == false) {str += '-';}std::reverse(str.begin(), str.end());return str;}
}// namespace phw// 以下代码在vs2013中不能体现,在vs2019下才能演示体现上面的特性。
class Person {
public:Person(const char *name = "", int age = 0): _name(name), _age(age) {}Person(const Person &p): _name(p._name), _age(p._age) {}Person &operator=(const Person &p) {if (this != &p) {_name = p._name;_age = p._age;}return *this;}// 强制生成移动构造和移动赋值Person(Person &&p) = default;Person &operator=(Person &&p) = default;~Person() {cout << "~Person()" << endl;}private:phw::string _name;// 自定义类型int _age = 1;     // 内置类型
};int main() {Person s1("张三", 18);Person s2 = s1;Person s3 = std::move(s1);cout << endl;return 0;
}

在这里插入图片描述

2.关键字delete

delete关键字用于显式地禁用某些特殊成员函数或运算符,以阻止它们在特定的上下文中被调用或使用。

使用delete关键字,可以在类的声明中删除以下函数:

  1. 删除默认构造函数:

    MyClass() = delete;
    

    这将禁用默认构造函数,阻止对象的无参创建。

  2. 删除复制构造函数和复制赋值运算符:

    MyClass(const MyClass&) = delete;
    MyClass& operator=(const MyClass&) = delete;
    

    这将阻止对象的复制,即禁止使用拷贝构造函数和复制赋值运算符进行对象的复制。

  3. 删除移动构造函数和移动赋值运算符:

    MyClass(MyClass&&) = delete;
    MyClass& operator=(MyClass&&) = delete;
    

    这将阻止对象的移动语义,即禁止使用移动构造函数和移动赋值运算符进行对象的移动操作。

  4. 删除析构函数:

    ~MyClass() = delete;
    

    这将阻止对象的销毁,即禁止调用析构函数进行对象的内存释放。

通过使用delete关键字,可以在编译期间捕捉到一些潜在的错误或不正确的使用。例如,如果尝试复制或移动被删除的函数,编译器将会产生错误。

示例:

class MySingleton {
private:MySingleton() = delete;  // 默认构造函数被删除MySingleton(const MySingleton&) = delete;  // 复制构造函数被删除MySingleton& operator=(const MySingleton&) = delete;  // 复制赋值运算符被删除public:static MySingleton& getInstance() {static MySingleton instance;return instance;}void doSomething() {// 执行操作}
};int main() {MySingleton& singleton = MySingleton::getInstance();singleton.doSomething();// 错误示例,尝试创建被删除的默认构造函数的对象// MySingleton singleton2;  // 编译错误return 0;
}

在上面的示例中,通过删除默认构造函数、复制构造函数和复制赋值运算符,实现了一个单例模式的类。这样,阻止了通过复制或拷贝方式创建多个实例。任何尝试复制的操作都会在编译时被捕获并产生错误。

总结来说,C++11的delete关键字为开发者提供了更大的灵活性,可以显式地删除某些函数,以避免在特定情况下的误用和错误。这是C++中一个强大的特性,有助于更好地控制类的行为和语义。

3.final与override

在C++11标准中,关键字finaloverride用于类的继承和虚函数的重写。它们提供了一种显式的方法来控制和标记继承关系和函数重写。

3.1 final

final关键字用于修饰类、虚函数或成员函数,表示它们不能被继承或重写。具体来说:

  • 当应用于类时,final关键字表示该类不能被其他类继承。
  • 当应用于虚函数时,final关键字表示该虚函数不能被派生类重写。
  • 当应用于成员函数时,final关键字表示该成员函数不能在派生类中被重写。

以下是使用final关键字的示例:

class Base final {// ...
};class Derived : public Base {  // 错误,无法继承被标记为final的类// ...
};class Base {
public:virtual void foo() const final;
};class Derived : public Base {
public:void foo() const override;  // 错误,无法重写被标记为final的虚函数
};class Base {
public:virtual void foo() const;
};class Derived : public Base {
public:void foo() const final;  // 错误,无法在派生类中重写被标记为final的成员函数
};

3.2 override

override关键字用于显式地标记派生类中的成员函数,以表明它们是基类中虚函数的重写版本。使用override关键字可以增强代码的可读性和可维护性,并帮助编译器检测错误。如果派生类中的函数声明使用了override关键字,但却没有重写基类中的虚函数,则会导致编译错误。

以下是使用override关键字的示例:

class Base {
public:virtual void foo() const{}
};class Derived : public Base {
public:void foo() const override{}  // 表示该函数是基类虚函数的重写版本
};class Base {
public:virtual void foo() const{}
};class Derived : public Base {
public:void foo() const{}  // 错误,没有使用override关键字重写基类的虚函数,编译器不会报错
};

override关键字的示例:

class Base {
public:virtual void foo() const{}
};class Derived : public Base {
public:void foo() const override{}  // 表示该函数是基类虚函数的重写版本
};class Base {
public:virtual void foo() const{}
};class Derived : public Base {
public:void foo() const{}  // 错误,没有使用override关键字重写基类的虚函数,编译器不会报错
};

注意,在C++11之前,虚函数的重写是隐式的,不需要使用override关键字。但是,使用override关键字可以提供更明确的语义和更好的编译时错误检测。


http://www.ppmy.cn/news/498263.html

相关文章

springcloud的组件及其作用以及面试相关问题

Spring Cloud 是一个用于构建分布式系统和微服务架构的开发工具包&#xff0c;它基于Spring框架&#xff0c;提供了一系列组件和模块来简化分布式系统的开发和管理。以下是一些常见的Spring Cloud组件及其作用的介绍&#xff1a; Eureka&#xff08;服务注册与发现&#xff09…

值得收藏的 10个 Android 手机恢复丢失文件的工具榜单

尽管我们尽可能避免这种情况&#xff0c;但有时我们还是会不小心删除 Android 设备上的重要文件。无论是照片、视频、文档还是任何其他形式的数据&#xff0c;数据丢失都会带来巨大的痛苦。不幸的是&#xff0c;Android 设备没有内置恢复工具。但是&#xff0c;有一些第三方恢复…

Java乐观锁实现文章点击量、收藏计数、点赞计数

Java乐观锁实现文章点击量、收藏计数、点赞计数 &#x1f4d4; 千寻简笔记介绍 千寻简笔记已开源&#xff0c;Gitee与GitHub搜索chihiro-notes&#xff0c;包含笔记源文件.md&#xff0c;以及PDF版本方便阅读&#xff0c;且是用了精美主题&#xff0c;阅读体验更佳&#xff0…

Mendix 10 树形组件分析及应用

一、前言 产品研发目标是服务于业务&#xff0c;解决具体业务问题&#xff0c;带来业务价值。 因此&#xff0c;任何产品功能的推出&#xff0c;都应该秉承“从实践中来&#xff0c;到实践中去”的原则&#xff0c;在实战中发现问题&#xff0c;通过新功能设计和功能改进解决…

kettle开发-Day38-超好用自定义数据处理组件

目录 前言&#xff1a; 一、半斤八两&#xff0c;都不太行 1、表输入&#xff0c;速度快&#xff0c;但不稳妥 2、稳的一批&#xff0c;但是慢的像蜗牛 二、各诉衷肠&#xff0c;合作共赢 1、表输入&#xff0c;高效数据插入 2、插入更新&#xff0c;一个都不能少 三、表输…

D. Survey in Class(贪心 + 分类讨论)

Problem - D - Codeforces Zinaida Viktorovna 的历史课上有 n 名学生。今天的作业包括 m 个主题&#xff0c;但是学生们准备时间很短&#xff0c;所以第 i 个学生只学习了从 li 到 ri &#xff08;包括&#xff09;的主题。 在课开始时&#xff0c;每个学生都将手举在 0 处。…

计算机主机连接电视机,如何将电脑连接到电视机上_台式电脑怎么连接电视机屏幕-win7之家...

现在的电视机都是液晶显示屏&#xff0c;会配有无线、蓝牙功能等等&#xff0c;有时我们需要把电脑内容投射在电视剧上&#xff0c;这就先要连接电视机在进行连接&#xff0c;那么如何将电脑连接到电视机上呢&#xff0c;下面小编给大家分享台式电脑连接电视机屏幕的方法步骤。…

[转载]家庭剧院音效再升级HDMI eARC相容未来效能

by Marshall Goldberg HDMI 2.1是HDMI最新的标准&#xff0c;能够提升达300%的视讯传输速度&#xff0c;并透过压缩功能进一步再提升300%&#xff0c;视讯频宽较HDMI 2.0的18Gbps高9倍。HDMI 2.1标准增加一系列新特性&#xff0c;包括动态HDR(Dynamic HDR)、可变更新率(Variabl…