C++11学习笔记(一)

__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






  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值