C++核心技术:基础内容

10 分钟阅读 1092 字 + 442 词
函数
函数的声明或者定义前面不管加不加extern说明,函数都具有外部链接性,它们可以跨翻译单元使用。
函数前加上static说明,指示函数具有内部链接性,符号名不视为公开,只能在当前翻译单元里使用。
对象和变量
对象可以有名字(变量名),也可以没有名字(动态对象和字符串字面量)
在 C++ 中, static 的全局变量具有内部链接性(internal linkage),而不是外部链接性(external linkage)。这意味着 static 的全局变量只能在定义它的翻译单元(通常是源文件)中访问,不能在其他翻译单元中访问。
静态存储器和线程局部存储期的对象内容初始化是0。
自动存储期和动态存储期的对象内容不确定
字符字面量的类型是int而不是char sizeof('A')等同于sizeof(int)
const表示其值不可更改,volatile表示其值可能会以意外的方式更改(因而会禁止优化操作)。volatile并没有多线程同步的语义,仅仅使用它是不够的,我们还需要原子量和新的内存模型。
c++中可以在头文件用const定义常量代替宏使用
重载
C++可以有两个同名函数,c++编译器会为他们生成不同的符号名称,称为名字重整
C++的规则是临时对象不能匹配非const的引用
类型转换
dynamic_cast :这是C里面不存在的转型方式,用来在带有虚函数的“动态对象’继承树里进行指针或引用的类型转换。比如,如果有shape指针ptr,我们可以使用 dynamic_cast(ptr)尝试把它转型成circle * 系统会进行需要的类型检查 ,并在 转型成功时返回一个非空指针,返回空指针则表示失败 (如当ptr实际指向的不是 circle,而是Rectangle)。 对于引用,转型失败则会抛异常 。通常认为这种转型方式是安全的。
static_cast : 这是“静态”转型方式 ,用在一些被认为较安全的场景下。你可以使用它在不同的数值类型之间进行转换,如从long到int,或者从 long long 到double--当转换有可能有精度损失时,就不能使用隐式类型转换,而得明确使用转型了。你也可以使用它把 void*转换成实际类型的指针(如int * )。你还可以用它把基类的指针转换成派生类的指针,前提条件是你能确认这个基类的指针确实指向一个派生类的对象。显然,对于最后一种场景,staticcast不如dynamic cast 安全,但由于 static cast 不需要进行运行期的检査,它的性能比dynamic_cast 要高 ,在很多情况下是个空操作。
const_cast :这种转型方式有可能不安全。它的目的是去掉一个指针或引用类型的cv限定,如从 const char* 转换到 char * 。这种转型的一种常见用途是把一个 C++的指针传递到一个const不正确的C接口里去。比如,C接口需要字符串参数,不会对其进行修改,那形参应该使用const char*,但实际有时使用了char * 。这在C里没有问题,因为字符串字面量的类型退化之后就是char * ,但C++里字符串字面量退化后是 constchar * (参见第10页)。 注意这种转型只是为了“欺骗”类型系统,让代码能通过编译 。如果你通过constcast操作指针或引用去修改一个const 对象,这仍然是错误的,是未定义行为,可能会导致奇怪的意外结果。
reinterpret_cast :这是对数据进行“重新解释”的最不安全的转型方式,用来在不相关的类型之间进行类型转换,如把指针转换成uintptrt。这种转换有可能得到错误的结果,比如,在存在多继承的情况下,如要把基类指针转成派生类指针,使用static_cast和使用reinterpret_cast 可能会得到不同的结果:前者会进行偏移量的调整,而 后者真的只是简单粗暴的硬转而已 ,因此结果通常是错的。又如,根据C++的严格别名规则,如果你用char或byte之外的类型的指针访问非该类型的对象(如通过int*访问double对象 ),会导致未定义行为。