C++ 不是 C 的一个超集:C++ 11 特性

这是很久之前的笔记,整理发出来并加了一点更新。

虽然C程序能用C++编译器编译,但是严格来说,C++ 不是 C 的一个超集。《为什么说C++不是C的超集? - 知乎》 这里有网友的解答,不再赘述。

C 和 C++ 混合使用的例子

// foo.h
#ifdef __cplusplus
extern "C" {
#endif

int add(int x, int y);

#ifdef __cplusplus
}
#endif

// foo.c
int add(int x, int y) {
    return x+y;
}

// main.cpp
#include "foo.h"
int main() {
    add(1, 2);
    return 0;
}

编译的命令是

gcc -c foo.c
g++ main.cpp foo.o -o main

C++ 中的 C++ 11 特性

一份个人的笔记,不是完整版,仅供参考

  • C++11 引入了 nullptr 关键字,专门用来区分空指针、0。nullptr 的类型为 nullptr_t

  • constexpr是限定了修饰的为编译期间可确定的常量,但是constexpr也是可以用于函数的,

constexpr int fibonacci(const int n) {
    return n == 1 || n == 2 ? 1 : fibonacci(n-1)+fibonacci(n-2);
}

Clang在处理constexpr时,在编译期间用一个C++的计算器计算constexpr的值,并且记录计算的次数。当次数超过一定值时,这个constexpr退化为非constexpr。

  • 使用 auto 进行类型推导的一个最为常见而且显著的例子就是迭代器。
    for(vector::const_iterator itr = vec.cbegin(); itr != vec.cend(); ++itr)
    for(auto itr = vec.cbegin(); itr != vec.cend(); ++itr)
    auto不能用于函数传参,因此下面的做法是无法通过编译的(考虑重载的问题,我们应该使用模板),auto 还不能用于推导数组类型:int arr[10] = {0},auto a[10] = arr
int array[] = {1,2,3,4,5};
for(auto &x : array) {
    std::cout << x << std::endl;
}
//& 启用了引用, 如果没有则对 arr 中的元素只能读取不能修改,不加却又修改不会报错。
  • decltype 声明某种类型
auto x = 1;
auto y = 2;
decltype(x+y) z;

尾置返回允许我们我们在参数列表后声明返回类型

template
auto f(T a,T b) -> decltype(*a)
{
  return *a;
}
  • int a[3] = {1,2,3} 列表初始化
struct A {
    int a;
    float b;
};
struct B {

    B(int _a, float _b): a(_a), b(_b) {}
private:
    int a;
    float b;
};
A a {1, 1.1};    // 统一的初始化语法
B b {2, 2.2};
  • std::initializer_list,允许构造函数或其他函数像参数一样使用初始化列表,
#include 
#include 

using namespace std;

int f(initializer_list list)
{
    int ans = 0;
    for(auto i : list)
        ans += i;
    return ans;
}
cout<
  • C++11 开始,连续的右尖括号将变得合法,并且能够顺利通过编译。
typedef int (*process)(void *);  //
定义了一个返回类型为 int,参数为 void* 的函数指针类型,名字叫做 process
using process = int(*)(void *);
// 同上, 更加直观
template 
using NewType = SuckType; // 合法
  • 默认模板参数
template
auto add(T x, U y) {
    return x+y;
}
  • 委托构造
class Base {
public:
    int v1,v2;
    Base() {
        v1 = 1;
    }
    Base(int value) : Base()  {  //成员初始化列表 委托 Base() 构造函数
        v2 = 2;
    }
    Base(int value) {  // 委托 Base() 构造函数
        Base();
        v2 = 2;
    }
};
  • 继承构造
class Test : public Base{
    public:
    test() {
        using Base::Base; // 继承构造
    }
}
  • 引入 override 关键字将显式的告知编译器进行重载,编译器将检查基函数是否存在这样的虚函数,否则将无法通过编译:
struct Base {
    virtual void foo(int);
};
struct SubClass: Base {
    virtual void foo(int) override; // 合法
    virtual void foo(float) override; // 非法, 父类没有此虚函数
};

final 则是为了防止类被继续继承以及终止虚函数继续重载引入的。

struct Base {
        virtual void foo() final;
};
struct SubClass1 final: Base {
};                  // 合法

struct SubClass2 : SubClass1 {
};                  // 非法, SubClass 已 final

struct SubClass3: Base {
        void foo(); // 非法, foo 已 final
};
  • 枚举类 此处默认 unsigned int , 未指定时将默认使用 int
enum class new_enum : unsigned int {
    value1,
    value2,
    value3 = 100,
    value4 = 100
};
  • 捕获错误
try{
  //
}catch(runtime_error e) {
  cout<

来自个人 C++ 文集

你可能感兴趣的:(C++ 不是 C 的一个超集:C++ 11 特性)