【__func__预定义标识符】
C99标准中就有的一个预定义标识符,其功能是 返回所在函数的名字
#include <string> #include <iostream> using namespace std; const char* hello() { return __func__; } const char* world() { return __func__; } int main() { cout << hello() << ", " << world() << endl; // hello, world }
在轻量级的调试中比较方便
hello()函数等同于
const char* hello() { static const char* __func__ = "hello"; return __func__; }
【#pragma和_Pragma操作符】
#pragma是一条预处理指令,应该都用过
#pragma once
等价于
#ifndef ___H__ #define ___H__ #endif
C++11提供了和其功能相同的操作符_Pragma,其格式如下
_Pragma(字符串字面量)
_Pragma("once");
【快速初始化成员变量】
在C++98中支持使用 ‘=’ 来 快速的、就地的 初始化成员变量,然而这种初始化却有很多限制,比如, 静态成员 必须是常量, 即使是常量的静态成员 ,也必须是 整形 或者 枚举型。而非静态成员变量的初始化则必须在构造函数中进行。
class Init{ public: Init(): a(0){} Init(int d): a(d){} private: int a; const static int b = 0; int c = 1; // 非静态成员,无法通过编译 static int d = 0; // 静态成员,但非常量,无法通过编译 static const double e = 1.3; // 非整型或者枚举,无法通过编译 static const char * const f = "e"; // 非整型或者枚举,无法通过编译 };
下面的这个类有多个构造函数,通过代码可以看出C++11的优势所在
#include <string> using namespace std; class Mem { public: Mem(int i): m(i){} private: int m; }; class Group { public: Group(){} // 这里就不需要初始化data, mem, name成员了 Group(int a): data(a) {} // 这里就不需要初始化mem, name成员了 Group(Mem m) : mem(m) {} // 这里就不需要初始化data, name成员了 Group(int a, Mem m, string n): data(a), mem(m), name(n){} private: int data = 1; Mem mem{0}; string name{"Group"}; };
【非静态成员的sizeof】
在之前的C++98中,sizeof运算符不能作用于 非静态成员变量,C++11对sizeof运算符做了扩展
#include <iostream> using namespace std; struct People { public: int hand; static People * all; }; int main() { People p; cout << sizeof(p.hand) << endl; // C++98 中通过, C++11 中通过 cout << sizeof(People::all) << endl; // C++98 中通过, C++11 中通过 cout << sizeof(People::hand) << endl; // C++98 中错误, C++11 中通过 }
【扩展的friend语法】
C++11中,friend的使用更为方便
class Poly; typedef Poly P; class LiLei { friend class Poly; // C++98 - 通过, C++11 - 通过 }; class Jim { friend Poly; // C++98 - 失败, C++11 - 通过 C++11中不需要使用类 }; class HanMeiMei { friend P; // C++98 - 失败, C++11 - 通过 C++11中甚至可以使用别名 };
虽然是简单的改动,但此时,我们可以为类模板声明友元了。下面看一个例子
// 为了方便测试,做了危险的定义 #ifdef UNIT_TEST #define private public #endif class Defender { public: void Defence(int x, int y){} void Tackle(int x, int y){} private: int pos_x = 15; int pos_y = 0; int speed = 2; int stamina = 120; }; class Attacker { public: void Move(int x, int y){} void SpeedUp(float ratio){} private: int pos_x = 0; int pos_y = -30; int speed = 3; int stamina = 100; }; #ifdef UNIT_TEST class Validator { public: void Validate(int x, int y, Defender & d){} void Validate(int x, int y, Attacker & a){} }; int main() { Defender d; Attacker a; a.Move(15, 30); d.Defence(15, 30); a.SpeedUp(1.5f); d.Defence(15, 30); Validator v; v.Validate(7, 0, d); v.Validate(1, -10, a); return 0; } #endif
#define private public的坏处显而易见,它不但降低了可读性,并且如果声明成员函数或成员变量时,不使用 private或public,默认是private。
接下来看看使用friend的类模板
template <typename T> class DefenderT { public: friend T; void Defence(int x, int y){} void Tackle(int x, int y){} private: int pos_x = 15; int pos_y = 0; int speed = 2; int stamina = 120; }; template <typename T> class AttackerT { public: friend T; void Move(int x, int y){} void SpeedUp(float ratio){} private: int pos_x = 0; int pos_y = -30; int speed = 3; int stamina = 100; }; //按照C++的定义,Defender和Attacker不会有友元,因而保持了很好的封装性 using Defender = DefenderT<int>; // 普通的类定义,使用int做参数 using Attacker = AttackerT<int>; #ifdef UNIT_TEST class Validator { public: void Validate(int x, int y, DefenderTest & d){} void Validate(int x, int y, AttackerTest & a){} }; using DefenderTest = DefenderT<Validator>; // 测试专用的定义,Validator类成为友元,可任意访问 using AttackerTest = AttackerT<Validator>; int main() { DefenderTest d; AttackerTest a; a.Move(15, 30); d.Defence(15, 30); a.SpeedUp(1.5f); d.Defence(15, 30); Validator v; v.Validate(7, 0, d); v.Validate(1, -10, a); return 0; } #endif