学习自:极客时间现代C++!
字面量(literal)是指在源代码中写出的固定常量,它们在 C++98 里只能是原生类型,如:
C++11 引入了自定义字面量,可以使用 operator"" 后缀 来将用户提供的字面量转换成实际的类型。C++14 则在标准库中加入了不少标准字面量。下面这个程序展示了它们的用法:
#include <chrono>
#include <complex>
#include <iostream>
#include <string>
#include <thread>
#include <bitset>
using namespace std::literals::chrono_literals;
using namespace std::literals::string_literals;
using namespace std::literals::complex_literals;
int main() {
std::cout << "i * i = " << 1i * 1i << std::endl;
std::cout << "Waiting for 500ms" << std::endl;
std::this_thread::sleep_for(500ms);
std::cout << "Hello world"s.substr(0, 5) << std::endl;
length l1 = length(1.0, length::metre);
length l2 = length(1.0, length::centimetre);
std::cout << l2.value << std::endl;
std::cout << (l1 + l2).value << std::endl;
}
现在我们有个类:
struct length {
double value;
enum unit {
metre,
kilometre,
millimetre,
centimetre,
inch,
foot,
yard,
mile,
};
static constexpr double factors[] =
{1.0, 1000.0, 1e-3,
1e-2, 0.0254, 0.3048,
0.9144, 1609.344};
explicit length(double v,
unit u = metre) {
value = v * factors[u];
}
};
length operator+(length lhs,
length rhs) {
return length(lhs.value +
rhs.value);
}
我们想完成两个length
的加法,我们可以这样写:
length l1 = length(1.0, length::metre);
length l2 = length(1.0, length::centimetre);
std::cout << l2.value << std::endl;
std::cout << (l1 + l2).value << std::endl;
有了自定义字面量后,我们可以重载""
:
length operator "" _m(long double v) { return length(v, length::metre); }
length operator "" _cm(long double v) { return length(v, length::centimetre); }
此时可以这样写:
// 1.0_m + 10.0_cm
std::cout << (1.0_m + 1.0_cm).value << std::endl;
直接前缀加0b
,跟8、16等进制用法一样!
// 二进制字面量
unsigned mask = 0b1101;
// 以十进制打印
std::cout << mask << std::endl;
// 打印二进制字面量
std::cout << std::bitset<4>(mask) << std::endl;
就是打印的时候得用bitset
才行。
按照自己想断的地方敲上'
即可!
// 数字分隔符
unsigned mk = 0b111'000'000;
double pi = 3.141'5926;
C++98 的 assert 允许在运行时检查一个函数的前置条件是否成立。没有一种方法允许开发人员在编译的时候检查假设是否成立。C++11引入了static_assert这个关键字,用来做编译期间的断言,因此叫做静态断言。
例如下面例子:
在编译期就可以判断条件是否成立(alignment是否是2的平方)。
const int alignment=5;
static_assert((alignment & (alignment - 1)) == 0, "Alignment must be power of two");
而assert
则做不到:
assert((alignment & (alignment - 1)) == 0);
在类的定义时,C++ 有一些规则决定是否生成默认的特殊成员函数。这些特殊成员函数可能包括:
我们可以改变缺省行为,在编译器能默认提供特殊成员函数时将其删除,或在编译器不默认提供特殊成员函数时明确声明其需要默认提供(不过,要注意,即使用户要求默认提供,编译器也可能根据其他规则将特殊成员函数标为删除)。
例如:
class myFun {
public:
myFun() = default;
myFun(const myFun &) = default;
myFun &operator=(const myFun &) = default;
myFun(myFun &&) = delete;
myFun &operator=(myFun &&) = delete;
~myFun() = default;
};
override 和 final 是两个 C++11 引入的新说明符。它们不是关键词,仅在出现在函数声明尾部时起作用,不影响我们使用这两个词作变量名等其他用途。这两个说明符可以单个或组合使用,都是加在类成员函数声明的尾部。
(1)override
功能:
作用:
(2)final
功能:
例如:
class A {
public:
virtual void foo();
virtual void bar();
void foobar();
};
class B : public A {
public:
void foo() override; // OK
void bar() override final; // OK
//void foobar() override;
// 非虚函数不能 override
};
class C final : public B {
public:
void foo() override; // OK
//void bar() override;
// final 函数不可 override
};
class D : public C {
// 错误:final 类不可派生
};