这是很久之前的笔记,整理发出来并加了一点更新。
虽然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<int>::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<T>
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 <iostream>
#include <initializer_list>
using namespace std;
int f(initializer_list<int> list)
{
int ans = 0;
for(auto i : list)
ans += i;
return ans;
}
cout<<f({1,2,3});
- C++11 开始,连续的右尖括号将变得合法,并且能够顺利通过编译。
typedef int (*process)(void *); //
定义了一个返回类型为 int,参数为 void* 的函数指针类型,名字叫做 process
using process = int(*)(void *);
// 同上, 更加直观
template <typename T>
using NewType = SuckType<int, T, 1>; // 合法
- 默认模板参数
template<typename T=int, typename U=int>
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<<e.what()<<endl;
}
来自个人 C++ 文集
网友评论