C++ 11新特性之语法甜点2

简介: C++ 11新特性之语法甜点2

概述

C++ 11中引入了许多简化编程工作的语法上的新特性,我们暂且美其名曰:“语法甜点”。书接上篇,我们继续介绍C++ 11中的这些“语法甜点”,也是第二篇关于“语法甜点”的文章。

语法甜点6:模板右边双括号

在C++ 03中,vector<vector<int>> vctTemp是一个非法的表达式,编译器会认为右边的>>是一个移位操作符,因此必须修改为:vector<vector<int> > vctTemp,即在右边的两个>中间添加一个空格。在C++ 11中,这将不再是一个问题,编译器将能够识别出右边的双括号是两个模板参数列表的结尾。

语法甜点7:static_assert

静态断言static_assert由一个常量表达式和一个字符串构成。在编译期间,将计算常量表达式的值;如果为false,字符串将作为错误信息输出。

#include <iostream>
using namespace std;
int main()
{
    char cNumber = 66;
    static_assert(sizeof(cNumber) == 4, "not an interger");
    return 0;
}


语法甜点8:初始化列表

在引入C++ 11之前,只有数组能使用初始化列表。在C++ 11中,vector、list等各种容器以及string都可以使用初始化列表了。初始化列表对应的类为initializer_list,vector、list等各种容器以及string之所以可以使用初始化列表,是因为它们重载了参数类型为initializer_list的构造函数(称为初始化列表构造函数)和赋值函数(称为初始化列表赋值函数)。

#include <iostream>
#include <vector>
#include <map>
using namespace std;
void Print(const initializer_list<int> &ilData)
{
    for (auto a : ilData)
    {
        cout << a << endl;
    }
}
int main()
{
    vector<int> vctNum = {1, 2, 3, 4, 5};
    map<string, string> mapID2Name = {{"92001", "Tom"}, {"92002", "Mike"}};
    string strText{"Hello World"};
    Print({});
    Print({1, 2});
    Print({1, 2, 3, 4, 5});
    return 0;
}



语法甜点9:默认或禁用函数

当我们定义了自己的带参数的构造函数时,编译器将不再生成默认的构造函数,如果此时想使用默认的构造函数,则必须显式地声明并定义不带参数的构造函数。在C++ 11中,我们可以使用default关键字来表明我们希望使用默认的构造函数。

类似的,当我们不想外部使用编译器自动生成的构造函数或赋值函数时,我们一般需要将其声明成protected或private的。在C++ 11中,我们可以使用delete关键字来表明我们不希望编译器生成默认的构造函数或赋值函数。

class CPerson
{
public:
    CPerson() = default;
    CPerson(const CPerson &person) = delete;
};


另外,=delete的声明(同时也是定义)也能适用于非自带函数,以禁止成员函数以特定的形参调用。

class CNoDouble
{
    void f(int i);
    void f(double) = delete;
};


若尝试以double的形参调用f(),将会引发编译错误,编译器不会自动将double形参转换为int再调用f()。 若要彻底禁止以非int的形参调用f(),可以将=delete与模板相结合。

复制  

class COnlyInt
{
    void f(int i);
    template<class T> void f(T) = delete;
};


语法甜点10:继承的构造函数

当一个派生类的某个函数隐藏了基类中的某个同名函数时,如果我们想在派生类中导出基类中的这个同名函数,可以通过using Base::Func的方式将基类中的这个同名函数引入到派生类的作用域内。但该方法只对普通成员函数有效,不能用于构造函数。

在C++ 11中,如果派生类认为基类的构造函数已经足够,则也可以使用using Base::Base的方式将基类的构造函数引入到派生类的作用域内。注意:此时派生类中的成员变量并没有进行初始化,所以应当对这些成员变量进行就地初始化。

#include <iostream>
#include <string>
using namespace std;

class CBase
{
public:
    CBase(int nValue) : m_nValue(nValue)
    {
        cout << "Base constructor with int" << endl;
    }

    CBase(double dValue) : m_nValue((int)(dValue * 10))
    {
        cout << "Base constructor with double" << endl;
    }

private:
    int m_nValue;
};

class CDerived : public CBase
{
public:
    // 使用 using 关键字引入基类的所有构造函数到派生类中
    using CBase::CBase;

   // 如果需要添加额外的成员变量或自定义构造函数,可以继续定义
    CDerived(const string &strText) : CBase((int)strText.size())
    {
        cout << "Derived constructor with string" << endl;
    }
};

int main()
{
    // 调用 CBase(int) 构造函数
    CDerived d1(5);

    // 调用 CBase(double) 构造函数
    CDerived d2(3.14);

    // 调用 CDerived(const string &) 构造函数
    CDerived d3("Hello World");

    return 0;
}

在上面的示例代码中,CDerived类通过using CBase::CBase语句,使得它可以直接使用CBase类中的所有公有和受保护的构造函数。这样,在创建CDerived对象时,可以根据传入的参数类型调用对应的基类构造函数来进行初始化。同时,CDerived类还可以拥有自己的构造函数,以处理新增成员变量的初始化和其他特殊逻辑。

相关文章
|
9天前
|
编译器 C++ 容器
【c++11】c++11新特性(上)(列表初始化、右值引用和移动语义、类的新默认成员函数、lambda表达式)
C++11为C++带来了革命性变化,引入了列表初始化、右值引用、移动语义、类的新默认成员函数和lambda表达式等特性。列表初始化统一了对象初始化方式,initializer_list简化了容器多元素初始化;右值引用和移动语义优化了资源管理,减少拷贝开销;类新增移动构造和移动赋值函数提升性能;lambda表达式提供匿名函数对象,增强代码简洁性和灵活性。这些特性共同推动了现代C++编程的发展,提升了开发效率与程序性能。
40 12
|
2月前
|
编译器 C语言 C++
☺初识c++(语法篇)☺
☺初识c++(语法篇)☺
|
6月前
|
编译器 程序员 定位技术
C++ 20新特性之Concepts
在C++ 20之前,我们在编写泛型代码时,模板参数的约束往往通过复杂的SFINAE(Substitution Failure Is Not An Error)策略或繁琐的Traits类来实现。这不仅难以阅读,也非常容易出错,导致很多程序员在提及泛型编程时,总是心有余悸、脊背发凉。 在没有引入Concepts之前,我们只能依靠经验和技巧来解读编译器给出的错误信息,很容易陷入“类型迷路”。这就好比在没有GPS导航的年代,我们依靠复杂的地图和模糊的方向指示去一个陌生的地点,很容易迷路。而Concepts的引入,就像是给C++的模板系统安装了一个GPS导航仪
209 59
|
5月前
|
安全 编译器 C++
【C++11】新特性
`C++11`是2011年发布的`C++`重要版本,引入了约140个新特性和600个缺陷修复。其中,列表初始化(List Initialization)提供了一种更统一、更灵活和更安全的初始化方式,支持内置类型和满足特定条件的自定义类型。此外,`C++11`还引入了`auto`关键字用于自动类型推导,简化了复杂类型的声明,提高了代码的可读性和可维护性。`decltype`则用于根据表达式推导类型,增强了编译时类型检查的能力,特别适用于模板和泛型编程。
54 2
|
6月前
|
存储 编译器 C++
【C++】面向对象编程的三大特性:深入解析多态机制(三)
【C++】面向对象编程的三大特性:深入解析多态机制
|
6月前
|
存储 编译器 C++
【C++】面向对象编程的三大特性:深入解析多态机制(二)
【C++】面向对象编程的三大特性:深入解析多态机制
|
6月前
|
编译器 C++
【C++】面向对象编程的三大特性:深入解析多态机制(一)
【C++】面向对象编程的三大特性:深入解析多态机制
|
6月前
|
C++
C++ 20新特性之结构化绑定
在C++ 20出现之前,当我们需要访问一个结构体或类的多个成员时,通常使用.或->操作符。对于复杂的数据结构,这种访问方式往往会显得冗长,也难以理解。C++ 20中引入的结构化绑定允许我们直接从一个聚合类型(比如:tuple、struct、class等)中提取出多个成员,并为它们分别命名。这一特性大大简化了对复杂数据结构的访问方式,使代码更加清晰、易读。
87 0
|
6月前
|
存储 编译器 C++
【C++】面向对象编程的三大特性:深入解析继承机制(三)
【C++】面向对象编程的三大特性:深入解析继承机制
|
6月前
|
编译器 C++
【C++】面向对象编程的三大特性:深入解析继承机制(二)
【C++】面向对象编程的三大特性:深入解析继承机制

热门文章

最新文章

下一篇
oss创建bucket