【C++】c++11新特性(一)

目录

{ }列表初始化

内置类型---对单值变量及数组的初始化

列表初始化时进行的类型转换

自定义类型---对类对象或结构的初始化

initializer_list

1. 定义接受 initializer_list 参数的构造函数

2. 在函数中使用 initializer_list 参数

3. 使用 initializer_list 与 vector 等容器

用于推断类型的关键字

auto  和  decltype

用于管理虚方法的说明符

final  和  override

final

1. 修饰类

2. 修饰虚函数

3. 修饰非虚成员函数

override


                                            


{ }列表初始化

内置类型---对单值变量及数组的初始化

下面是将花括号列表初始化用于单值变量的情形 . 如下代码:

可以看出 变量 num1 和 变量num2 都被初始化为6 ;因此,采用大括号这种初始化方式可使用等号(=),也可以省略不写

那如果花括号里我们什么都不写呢?那么它的值会是什么如下代码:

如上可看到花括号中如果什么都不写,这种情况下变量将被初始化为 0

将花括号列表初始化用于数组初始化的情形 ,数组在之前就可使用列表初始化,但c++11对列表初始化新增了一些功能。

      1. 初始化数组时可以省略等号(=);

      2. 在花括号内可以不包含任何东西,此时,所有元素都被初始化为0,这与单值变量初始化类似

如下代码:

此外,对列表初始化语法用于 new表达式中:

前两行只是申请了内存空间(即对于单个对象申请了一个int型大小的空间,对于多个对象申请了连续的4个大小的int型空间);后两行既申请了空间又对其进行了初始化。

列表初始化时进行的类型转换

c++11这种列表初始化常用于复杂的数据类型提供值列表,相较于c(内置类型)的初始化方式来说,c++11列表初始化对类型转换的要求更加严格。具体来说就是不允许把更宽的类型转换为窄的类型,比如:int-->char 不允许(当int的范围超出char时)。如下代码演示:

       通过上面的代码可以看到,162行是 c 风格的初始化,把一个int类型的值为3556(已超出char的范围)赋给char类型变量,编译器只给了警告:发生截断,但还是可以通过的;而使用c++11的大括号{}列表初始化编译器就会直接报错,是不能通过编译的。因此,使用列表初始化时要注意类型间的转换

说明:列表初始化是禁止大类型向小类型转换的,上面是单值对象,数组也是一样的

自定义类型---对类对象或结构的初始化

将花括号列表初始化用于类对象,但要提供与某个构造函数的参数列表匹配的内容,并用大括号括起来。

花括号列表初始化可以用于类对象(要隐式类型转换,调用构造函数),是该类要支持单参数或多参数的构造函数(可以是带缺省值的) ;

说明:当用于new表达式 (想要申请并初始化多个对象) 时,如果申请的 对象个数 与 大括号中 初始化的个数不符(小于),这时,剩余的个数会去调用默认的构造函数初始化,此时需要有默认构造函数才行,否则会有编译错误:如:上面代码中 289 行,就需要提供默认构造函数才行,要么就对象个数与大括号中初始化数一致。

将花括号列表初始化用于结构体的情形

initializer_list

initializer_list 是一个模板类,它允许使用花括号初始化器({})来初始化对象。initializer_list 通常用于构造函数和函数参数以接受任意数量的元素进行初始化

这提供了一种方便的方式来初始化容器、数组或其他集合类型。

下面是initializer_list 的用法

1. 定义接受 initializer_list 参数的构造函数

#include <iostream>
#include <vector>
#include <initializer_list>
using namespace std;class MyClass 
{
public:MyClass(initializer_list<int> il) {for (auto& e : il) {data.push_back(e);}}void print()  {for (auto& e : v) {cout << e << " ";}cout << endl;}private:vector<int> v;
};int main() 
{MyClass mc = { 1, 2, 3, 4, 5 }; // 使用花括号初始化  mc.print(); // 输出: 1 2 3 4 5  return 0;
}

2. 在函数中使用 initializer_list 参数

#include <iostream>
#include <initializer_list>
using namespace std;void print_list(initializer_list<int> il) 
{for (auto& e : il) {cout << e << " ";}cout << endl;
}int main() 
{print_list({ 10, 20, 30, 40, 50 }); // 输出: 10 20 30 40 50  return 0;
}

  3. 使用 initializer_list 与 vector 等容器

vector和其他STL容器通常都有接受initializer_list参数的构造函数,因此,可以直接使用花括号初始化:

int main() 
{vector<int> v = { 1, 2, 3, 4, 5 };for (auto& e: v) {cout << e << " ";}cout << endl; // 输出: 1 2 3 4 5  return 0;
}

说明:

        1.  initializer_list对象只用于初始化,它们不是真正的容器,不支持修改操作(如push_back

        2. 如果类有多个构造函数,并且其中一些接受单个参数,可能会遇到与隐式类型转换相关的歧义。此时,可能需要使用explicit关键字来防止不期望的隐式转换

initializer_list提供了一种方便且灵活的方式来初始化对象和集合,使得代码更加清晰和易读

用于推断类型的关键字

auto  和  decltype

关键字auto之前是一个存储类型的说明符,但c++11重新定义了auto的含义:将 其用于实现自动类型推断。要求必须进行显示初始化,让编译器将定义对象的类型设置为初 始化值的类型

关键字decltype, 把变量的类型声明为表达式指定的类型。

1. 若decltype 指定的表达式没有括号,则所声明变量的类型和指定表达式的类型相同

代码中所声明的变量的类型 z、u、w 与 decltype括号中所指定的类型一样

注意:虽然 m和n 都是引用,但表达式 m+n 不是引用,因此,mn 的类型是 int 而不是 int&

是两个int的和;

2. 若decltype 指定的表达式是函数调用,则所声明变量的类型函数返回值的类型相同

注意:编译器是通过查看函数的原型 确定返回类型,而不会实际调用函数

3. 若decltype 指定的表达式是一个左值且带有括号,则所声明变量的类型左值的引用

上面代码中,q 是被括号括起来的,则声明的变量 v 的类型是 左值 q 的引用,注意与无括号的对比;

注意:若用decltype 声明的变量 是上面代码中 323 行 的形式 就必须要引用一个左值,否则编译会报错;如:decltype((q))   v;  //erro

说明:括号并不会改变表达式的值 和 左值性

用于管理虚方法的说明符

final  和  override

final

final 可用于修饰类、虚函数final 关键字主要用于那些设计为不应该被继承或不应该被重写的类和方法。使用final 可以增强代码的可读性和可维护性,因为它明确指出了哪些类和方法是封闭的,不应该被修改或扩展。同时,它也有助于防止由于错误地继承或重写而引起的潜在问题

下面是final的几种用法

1. 修饰类

final用于类时,表示这个类不能被继承。这有助于防止不希望被继承的类被意外地继承

class Base final 
{// ... 类成员 ...  
};// 下面的代码会编译错误,因为Base类被声明为final  
class Derived : public Base 
{// ... 类成员 ...  
};
2. 修饰虚函数

当 final 用于虚函数时,表示这个虚函数在派生类中不能被重写。这有助于确保某些关键的函数行为在类的继承体系中保持不变

class Base {
public:virtual void func() final {// ... 函数的实现  }// ... 其他成员 ...  
};class Derived : public Base {
public:// 下面的代码会编译错误,由于 func()函数在Base类中被声明为final  void func()  // ... 想要重写的函数实现 ... {// ... 函数的实现}
};
3. 修饰非虚成员函数

虽然非虚成员函数也可以使用final关键字,但这通常没有太多实际意义,因为非虚成员函数本来就不能被重写。

override

  override关键字用于显式地指示一个成员函数在派生类中重写了基类中的虚函数。使用override的好处在于,它提供了编译时的检查,确保你确实重写了基类中的某个虚函数。如果基类中没有相应的虚函数,编译器会报错,从而防止潜在的错误。

下面是override的用法:   

class Base {
public:virtual void func1() {// 基类虚函数的实现  }// 非虚函数,不能被重写  void func2(){// ...  }
};class Derived : public Base {
public:// 使用override关键字显式地表示我们重写了Base类的func1函数,// 也可以不使用override,但使用override可以提供额外的检查  void func1() override{// 派生类重写func1函数的实现  }// 尝试重写Base类的func2函数,但由于func2不是虚函数,这里会编译错误  // 即使使用了override关键字,也无法将其变为虚函数  void func2() override{// 尝试重写的实现,但会导致编译错误  }
};

在上面的演示中,Derived类继承了Base类,并重写了func1这个虚函数。通过在派生类的成员函数声明后添加override关键字,告诉编译器这个函数是重写的,并且编译器会检查基类中是否存在相应的虚函数。如果基类中没有相应的虚函数,编译器将报错。

注意:

       即使不使用override关键字,只要函数签名(包括返回类型和参数列表)与基类中的虚函数匹配,派生类中的成员函数也会被视为重写了基类的虚函数。但是,使用override提供了额外的安全性,因为它强制要求基类中存在一个可重写的虚函数。

只有虚函数才能被重写。如果尝试重写非虚函数,即使使用了override关键字,也会导致编译错误


      

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/595537.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基础总结篇:Activity生命周期

private int param 1; //Activity创建时被调用 Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.i(TAG, “onCreate called.”); setContentView(R.layout.lifecycle); Button btn (Button) findViewById(R.id.…

柯桥外语机构商务英语学习,“五星级”酒店到底是five star还是five stars?这个千万别搞错!

“五星级酒店”的英语表达 关于酒店&#xff0c;大家都知道有星级之分&#xff1b;其中&#xff0c;最高级的酒店当属“五星级”了&#xff1b; 那么问题来了&#xff0c;这个“五星级”的英语&#xff0c;究竟是“five star”&#xff0c;还是“five stars”呢&#xff1f; 其…

SAP ERP出海解决方案提供商【工博科技】,为中国企业“出海”护航

当今高质量发展成为主题&#xff0c;中国企业正积极将创新成果、产品、服务“走出去”。然而出海企业面临着充满不确定性的国际环境带来的风险管控挑战和全球化经营带来的竞争挑战&#xff0c;必须要不断提升风险管控能力和综合竞争实力。其中&#xff0c;成熟的数字化能力可以…

MySQL中的redo log 和 undo log

undo log和redo log 先引入两个概念&#xff1a; 当我们做了一些操作 (update/delete/insert)&#xff0c;提交事务后要操作MySql中的数据。 为了能够提升性能&#xff0c;引入了两块区域&#xff1a;内存结构和磁盘结构。 磁盘结构&#xff1a; 主要存储的就是数据页&#x…

非关系型数据库——Redis基本操作

目录 一、Redis数据库常用命令 1.Set——存放数据 2.Get——获取数据 3.Keys——获取符合条件的键值 4.Exists——判断键值是否存在 5.Del——删除指定键值 6.Type——获取键值对应的类型 7.Rename——对已有键值重命名&#xff08;覆盖&#xff09; 8.Renamenx——对…

Oracle 中 where 和 on 的区别

1.Oracle 中 where 和 on 的区别 on&#xff1a;会先根据on后面的条件进行筛选&#xff0c;条件为真时返回该行&#xff0c;由于on的优先级高于left join&#xff0c;所以left join关键字会把左表中没有匹配的所有行也都返回&#xff0c;然后生成临时表返回,执行优先级高于…

【.Net】Polly

文章目录 概述服务熔断、服务降级、服务限流、流量削峰、错峰、服务雪崩Polly的基本使用超时策略悲观策略乐观策略 重试策略请求异常响应异常 降级策略熔断策略与策略包裹&#xff08;多种策略组合&#xff09; 参考 概述 Polly是一个被.NET基金会支持认可的框架&#xff0c;同…

C语言--指针终章

目录 1. sizeof和strlen的对⽐ 1.1 sizeof 1.2 strlen 1.3 sizeof 和 strlen的对⽐ 2. 数组和指针的理解——题目理解 2.1.sizeof 代码1&#xff1a; 代码2&#xff1a; 代码3&#xff1a; 代码4&#xff1a; 代码5&#xff08;二维数组&#xff09;&#xff1a; 2.2…

分类预测 | Matlab实现DRN深度残差网络数据分类预测

分类预测 | Matlab实现DRN深度残差网络数据分类预测 目录 分类预测 | Matlab实现DRN深度残差网络数据分类预测分类效果基本介绍程序设计参考资料 分类效果 基本介绍 1.Matlab实现DRN深度残差网络数据分类预测&#xff08;完整源码和数据&#xff09;&#xff0c;运行环境为Matl…

【Docker系列】在 Linux 上安装 Docker Compose 的简明步骤

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

7.java openCV4.x 入门-Mat之转换、重塑与计算

专栏简介 &#x1f492;个人主页 &#x1f4f0;专栏目录 点击上方查看更多内容 &#x1f4d6;心灵鸡汤&#x1f4d6;我们唯一拥有的就是今天&#xff0c;唯一能把握的也是今天建议把本文当作笔记来看&#xff0c;据说专栏目录里面有相应视频&#x1f92b; &#x1f9ed;文…

单一职责原则

1.1 阅读干吗不直接用手机&#xff1f; 电子阅读器比较专注&#xff0c;而手机功能比较多&#xff0c;影响专注。 1.2 手机不纯粹 手机确实很方便。但是现在的手机就是一台小型智能电脑。它不仅能打电话&#xff0c;还能听音乐、看电影电视、与个人交流、与一群人群聊&#…