有趣的知识点__cplusplus
__cplusplus 其实被定义为一个整数 , C++03 中被定义为199711L , C++11 中被定义为201103L .
可以通过下面的代码检测编译器是否支持C++11 .
枚举
枚举的作用域即是它所在的namespace, 有是他的父 作用域 。
例子 :
;Type t1 = General; // Correct Type t2 = Type::General ; // Also correct 实用的改进Featuresizeof
C++98 的sizeof不能使用非static的类成员作为参数, C++ 11 则可以 .
例子 :
class Test{public:int m_int;static int s_int;};::cout;using std::endl;int main(){;}friend
C++11的friend 关键字不必再写class . 支持模板作为friend. 如果模板的实例化是一个基本类型, 那么就忽略这个友元.
例子
template<typename T>class Test {public:friend T; // C98 需要写出 friend class T , 且 T 需要为具体的类名 .private:int a;};class FriendClass ;typedef TestNoFriend Test<int> ;typedef TestHasFriend Test<FriendClass>;final
对于虚函数(非纯虚) , 使用final关键字可以阻止派生类重载继续这个接口.
例子:
#include <iostream>using std::cout;using std::endl;class GrandPa{public:() = 0;};class Father : public GrandPa{public:() final { cout<<“Father is always correct ! “<<endl;}};class Son : public Father{public:void Print() { /* TODO want son want*/} //error: overriding final function ‘virtual void Father::Print()’};override
使用override关键字修饰函数, 指明这个函数是重载了父类的接口, 如果不是,则会编译出错 .
例子:
class Father{public:(){}};class Son : public Father{public:() override {} //error: ‘virtual void Son::AA()’ marked override, but does not override};模板
具体例子请自习查阅书籍.
构造函数 继承构造函数的 用途: 1.1.1 父类的构造函数众多 1.1.2 派生类添加的数据项较少, 可以通过指定默认值(C++11) 的方式初始化 注意: 1.2.1 多重继承的时候注意构造函数冲突问题 委派构造函数 用途 2.1.1 各种构造函数有部分相同的工作 2.1.2 在初始化列表中使用, 类似父类构造函数的使用 注意: 2.3 注意不应该产生环状依赖
例子 :
::cout;using std::endl;class Father{public:Father() : Father(1) {} // 委派给只有一个参数的构造函数 .Father(int i) : Father(i,2){} // 委派给最详细赋值的构造函数 .Father(int i, int j) : a(i) , b(j){}void Print() {cout<<“a :”<<a<<” b : “<<b<<endl; }private:int a;int b; };class Son : public Father{public:using Father::Father; // 继承父类的构造函数void Print(){Father::Print();cout<<“c :”<<c<<endl;}private:int c = 3 ; // C++11 可以直接对非static成员进行初始化.};int main(){Son a;Son b(3);Son c(3,4);a.Print();b.Print();c.Print();return 0;}初始化列表 便捷初始化// C++98 error , C++11 pass int a[] = { 1 , 2, 3} ;int b[] { 4, 5, 6} ;vector<int> c(1,2,3); 防止类型收窄int i = 1024;int j = 10 ;char c = {i}; // error , narrowing and miss datachar c = {j}; // pass , narrowing but no data miss.新的Feature右值 , 右值引用 , 移动语义 , std::move
值的分类
左值右值
移动语义在需要深层拷贝的类有巨大作用(不必重新开辟内存). 理论上 T( const T && ) 是可以的 , 但是没有意义, 移动语义决定了我们应该去改变这个右值 .
std::move 将一个左值转化为右值 .
std::move(a) 返回a转化为的右值 , 但是a 本身并没有消亡, a 变量被移动函数改变过之后, 或许数据已经混乱, 不应该继续作为普通左值使用.
利用引用折叠语义, 实现模板的参数可以接受各种类型的数据 , 实现完美转发template< class T> void IamForwarding< T && t>{//IrunCodeActually(static_cast<T && t> );IrunCodeActually(std::forward(T && t> );/*真正使用的时候, 若T是 A & , 则 && 折叠 , 参数是左值.若T是 A &&, 则 && 折叠 , 参数是右值.*/}自定义字面值
定义函数 : T operator “”_X( P ) {}
其中T为目标类, _X 为字面值后缀 , P 是 ” ” 部分的类型 , 作为参数传入(整形 , 浮点 , 字符) .
然后继续努力,把让自己跌倒的石头搬掉或绕过去,不就解决问题了吗?