C++11学习笔记(一)

来源:互联网 发布:大数据就业前景 编辑:程序博客网 时间:2024/05/18 12:39

__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#endifclass 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_TESTclass 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_TESTclass 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






1 0
原创粉丝点击