关于C++一些有趣的知识

Effective C++
目录
1-------C与C++的一些联系
2-------Prefer consts, enums and inlines to #define
3-------关于static, const, static const ,in-class初始化限制
4-------为什么static成员类外初始化不可以再加static?
5-------待更新。。。

  1. 一开始,C++只是C加上了一些面向对象的特性。C++最初的名称C with Classes也反映了这个血缘关系。
  2. Prefer consts, enums, and inlines to #define.
    也就是说,宁可以编译器替换预处理器,因为或许#define不被视为语言的一部分。这正是它的问题所在。当你做出这样的事情。
    #define ASPECT_RATIO 1.653
    记号名称ASPECT_RATIO也许从未被编译器看见;也许在编译器开始处理源码之前他就被预处理器移走了。于是记号名称ASPECT_RATIO有可能没有进入记号表(symbol table)内。于是当你运用此常量但获得一个编译错误信息时,可能会带来困惑,因为这个错误信息也许会提到1.653而不是ASPECT_RATIO。如果ASPECT_RATIO被定义在一个非你所写的头文件内,你肯定对1.653以及它来自何处毫无概念,于是你将因为追踪它而浪费时间。这个问题也可能出现在记号式调试器(symbolic debugger)中,原因相同:你所使用的名称可能并未进入记号表(symbol table)。
    解决之道是以一个常量替换上述的宏(#define):
    const double AspectRatio = 1.653;//大写名称常用于宏,因此这里改变名称写法。(这本书的这个地方很细节,我喜欢)
    作为一个语言常量,AspectRatio肯定会被编译器看到,当然就会进入记号表内。此外对于浮点常量(floating point constant,就像本例)而言,使用常量可能比使用#define导致较小量的码,因为预处理器“盲目地将宏名称ASPECT_RATIO替换为1.653”可能导致目标码(object code)出现多分1.653,若改用常量AspectRatio绝不会出现相同情况。
    当我们以常量替换#define,有两种情况值得说说。第一是定义常量指针(constant pointers)。由于常量定义式通常被放在头文件内(以便被不同的源码含入),因此有必要将指针(而不只是指针所指之物)声明为const。例如若要在头文件内定义一个常量的char *based字符串,你必须写const两次:
    const char *const authorName = “rookiezhao”;
    关于const的意义和使用(特别是当它与指针结合时),条款3有完整的讨论,这里值得注意的是,string对象通常比其前辈char *base合宜,所以上述的authorName往往定义成这样更好写:
    const std::string authorName(“rookiezhao”);
    第二个值得注意的是class专属常量。为了将常量的作用域(scope)限制于class内,你必须让它成为class的一个成员(member);而为确保此常量至多只有一份实体,你必须让它成为一个static成员:
class GamePlayer {
private:
	static const int NumTurns = 5; //也许有些编译器不支持这样的语法
	int scores[NumTurns];
}

通常C++要求你对所使用的任何东西提供一个定义式,但如果他是个class专属常量又是static且为整数类型(intergral type,例如 ints, chars, bools),则需特殊处理。只要不取他们的地址,你可以声明并使用他们而无需提供定义式。但如果你要取得某个class专属常量的地址,或纵使你不取其地址而你的编译器却(不正确地)坚持要看到一个定义式,你就必须另外提供定义式如下:

const int GamePlayer::NumTurns; //NumTurns的定义

请把这个式子放进一个实现文件而非头文件。由于class常量已在声明时获得初值,因此定义式不可以再设初值。
顺带一提,请注意,我们无法利用#define创建一个class专属常量,因为#defines并不重视作用域(scope)。一旦宏被定义,它就在气候的编译过程中有效(除非在某处被#undef)。这意味着#define不仅不能够用来定义class专属常量,也不能够提供任何封装性,也就是说没有所谓的private #define这样的东西。而当然const成员变量是可以被封装的,NumTurns就是。
旧编译器也许不支持上述语法,它们不允许static成员在其声明式上获得初值。此外所谓的“in-class初值设定”也只允许对整数常量进行。如果你的编译器不支持上述语法,你可以将初值放在定义式:

class GamePlayer{
private:
	static const double Value; //static class常量声明 位于头文件
	...
}
const double GamePlayer::Value = 1.35; //static class常量声明,位于实现文件内,不可以加上static关键字

为什么不能加上static?
个人理解,static是有scope限制的,在类内加了static限制,就表明这个static成员为本类所有。当你在类外再加上static的时候,相当于限定了这个static成员为文件内全局的。类外初始化值的时候一般都会加上类作用域。这个时候再加上static限制就会造成冲突。所以不能类外初始化类内的static成员不可以再加上static。

关于static、const、static const成员初始化区域你了解多少?
static 非 const成员不可以在类内初始化,也不可以在构造函数以及初始化成员列表中初始化。
非static const成员,不可以在类内初始化,可以在初始化成员列表中初始化,不可以在构造函数中初始化。
static const成员可以在类内、类外初始化(旧的编译器可能不允许)。不能再初始化成员列表和构造函数中初始化。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值