C++11学习笔记(一)
2015-11-25 20:15
369 查看
【__func__预定义标识符】
C99标准中就有的一个预定义标识符,其功能是 返回所在函数的名字
在轻量级的调试中比较方便
hello()函数等同于
将其用在初始化列表中也是可以的,但是不能作为成员函数参数的默认值,因为参数声明时,__func__尚未定义
【#pragma和_Pragma操作符】
#pragma是一条预处理指令,应该都用过
等价于
C++11提供了和其功能相同的操作符_Pragma,其格式如下
上面的效果,用_Pragma来实现的代码如下
由于_Pragma是一个操作符,所以相比#pragma,在宏定义中更为灵活方便
【快速初始化成员变量】
在C++98中支持使用 ‘=’ 来 快速的、就地的 初始化成员变量,然而这种初始化却有很多限制,比如, 静态成员 必须是常量, 即使是常量的静态成员 ,也必须是 整形 或者 枚举型。而非静态成员变量的初始化则必须在构造函数中进行。
C++11中,允许对非静态成员通过 ‘=’ 或者 '{ }'符号进行就地初始化,同时保留了 成员列表初始化 的方式,不过,如果两者同时使用,C++11新的初始化 非静态成员 的方式 要优先于 传统的成员列表初始化。
下面的这个类有多个构造函数,通过代码可以看出C++11的优势所在
不过对于 静态的非常量成员变量,C++11与C++98保持了一致
【非静态成员的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的使用更为方便
虽然是简单的改动,但此时,我们可以为类模板声明友元了。下面看一个例子
// 为了方便测试,做了危险的定义
#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
代码
接下来看看使用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
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__; }
将其用在初始化列表中也是可以的,但是不能作为成员函数参数的默认值,因为参数声明时,__func__尚未定义
【#pragma和_Pragma操作符】
#pragma是一条预处理指令,应该都用过
#pragma once
等价于
#ifndef ___H__ #define ___H__ #endif
C++11提供了和其功能相同的操作符_Pragma,其格式如下
_Pragma(字符串字面量)
上面的效果,用_Pragma来实现的代码如下
_Pragma("once");
由于_Pragma是一个操作符,所以相比#pragma,在宏定义中更为灵活方便
【快速初始化成员变量】
在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中,允许对非静态成员通过 ‘=’ 或者 '{ }'符号进行就地初始化,同时保留了 成员列表初始化 的方式,不过,如果两者同时使用,C++11新的初始化 非静态成员 的方式 要优先于 传统的成员列表初始化。
下面的这个类有多个构造函数,通过代码可以看出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"}; };
不过对于 静态的非常量成员变量,C++11与C++98保持了一致
【非静态成员的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
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- 关于指针的一些事情
- c++ primer 第五版 笔记前言
- share_ptr的几个注意点
- 局域网与广域网接口标准
- Lua中调用C++函数示例
- Lua教程(一):在C++中嵌入Lua脚本
- Lua教程(二):C++和Lua相互传递数据示例
- web标准知识——从p开始,循序渐进
- C++联合体转换成C#结构的实现方法
- 网页打开新窗口target=_blank不符合标准
- C++编写简单的打靶游戏
- C++ 自定义控件的移植问题
- C++变位词问题分析
- C/C++数据对齐详细解析
- C++基于栈实现铁轨问题
- C++中引用的使用总结
- 使用Lua来扩展C++程序的方法
- C++中调用Lua函数实例