您的位置:首页 > 编程语言 > C语言/C++

C++11学习笔记(一)

2015-11-25 20:15 369 查看
【__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__;
}

将其用在初始化列表中也是可以的,但是不能作为成员函数参数的默认值,因为参数声明时,__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++ 标准