c++笔记(1)
优秀是一种习惯,先来碗鸡蛋汤在继续~~
0、学好编程有四个方面:语言、算法 、数据结构、系统调用和设计
C++是最难学的语言了,像难以驯服的野兽~~
- (学习java有助于学会怎么更好地使用C++)
- 1.在调用虚函数的时候,C++运行时将首先查找对象所对应的虚函数表,然后根据虚函数表中所记录的地址来调用相应的虚函数实现。C++在运行时动态决议的基本方法就是虚函数
2.函数重载决议是在编译时完成的。
C / C++的一些区别:
3.结构 & 联合
C 的结构(struct)不是一种类型,使用时得带着关键字struct,一般用typedef来避免这种不便。
C++ 的结构几乎等价于类,只是缺省的访问权限为public而非private。
C++ 的联合(union)可以有成员函数,甚至可以有构造和析构函数。
要想让一个 C 函数真正没有参数,得用void: void foo(void);
对 C++ 来说,一个不带参数的函数就是指不接受参数。往参数列表里放void是多余的。
5.提升void*
C 会自动提升(promote)void*:
int* pi = malloc(sizeof(int));
函数malloc返回void*,赋值给int*时不需要显式转型。而 C++ 必须显式转型:
int* pi = static_cast<int*>(malloc(sizeof(int)));
6. C 的 consts(特指用 const 关键字修饰的常量)不可以用在常量表达式中。这让 C 的 consts 远不如 C++ 的有用,也让 C 依赖于预处理器,而 C++ 程序员则可以使用有适当类型和作用域的 consts。
7.前置声明
C 代码块中,所有声明必须出现在任何程序语句之前,比如函数定义时,先声明所有局部变量
而 C++ 的声明,诸如int ival;,其自身就是一个程序语句,也因此可以出现在程序文本中的任何位置。
8.size_t
-
size_t是sizeof返回值的类型
-
size_t是一个typedef //size_t一般就是unsigned int的typedef
-
sizeof不是一个函数,它是一个编译时操作符
-
size_t能够表示任何类型理论上可能的数组的最大大小
9.按存储分类的对象
C/C++ 的对象,按存储类型分为以下几种:
-
自动的(auto, register)
-
静态的(static)
-
自由存储的(free-store)
到了 C++11,auto这个关键字就被拿来另作他用了:auto可以让编译器从变量的初始化上自动推断出它的类型:
auto a = std::max(1.0, 4.0); // 编译器推断出 a 的类型为 double
10.
以文件操作为例,C 的做法是:
{
FILE* file = fopen( ... );
// ...
fclose(file);
}
而 C++ 就方便很多,不需要手动关闭文件,因为std::ofstream在析构时会自动释放文件资源,即使中途有异常发生也不会出现问题。
{
std::ofstream file( ... );
// 继续操作文件 ...
} // 在此 file 对象被自动清理,它的析构函数负责释放文件资源。
11.联合(union)的元素共用同一块内存空间,联合的大小就是最大元素的大小。
12.类
第一点:访问控制作用于类而非对象
第二点:访问控制作用于编译时而非运行时
成员函数指针 可能不单单是一个指针(指向成员函数代码的起始地址),它可能是一个小型的结构,编码了很多额外的信息,比如函数是否虚拟(virtual)、是否多继承,等等
13.特指以const关键字修饰的变量
两个编译单元里的常量,即使包含自同一个头文件,也互不干扰。
// const.h
const int INT = 1;
// test_1.cc
#include "const.h"
const void* get_int_address_1() { return &INT; }
// test_2.cc
#include "const.h"
const void* get_int_address_2() { return &INT; }
// main.cc
extern const void* get_int_address_1(); //main中,需要的函数在别的文件,那就用一下extern
extern const void* get_int_address_2();
int main() {
// 地址不一样,说明各有一份
assert(get_int_address_1() != get_int_address_2());
}
编译单元test_1.cc和test_2.cc都包含了const.h里的常量INT,但其实它们各有一份自己的INT,互不干扰。
如果头文件里定义的常量不是int,double这种原始类型,必须加上关键字static,否则多个编译单元在链接(link)时,会报错说有重复定义。
// const.h
static const std::string STR = "test";
14.转型C++ 提供了四个转型操作符。
-
static_cast中的static是指编译时,转型失败的话就不能编译。
-
dynamic_cast中的dynamic是指运行时,转型失败的话会返回NULL(转指针时)或引发std::bad_cast异常(转引用时)。
-
reinterpret_cast意为重新解释,转型时不做任何检查。
-
const_cast只是去掉常量性。
感谢:http://www.cnblogs.com/sujz/archive/2011/05/12/2044362.html
static_cast 用法:static_cast < type-id > ( expression ) 该运算符把expression转换为type-id类型,但没有运行时类型检查来保证转换的安全性。注意:static_cast不能转换掉expression的const、volitale、或者unaligned属性。
dynamic_cast 用法:dynamic_cast < type-id > ( expression ) 该运算符把expression转换成type-id类型的对象。Type-id必须是类的指针、类的引用或者void *
reinpreter_cast 用法:reinpreter_cast<type-id> (expression) type-id必须是一个指针、引用、算术类型、函数指针或者成员指针。
const_cast 用法:const_cast<type_id> (expression) 该运算符用来去除类型的const或volatile属性。
15.C++跟JAVA的一些区别:
好像吃锅贴饺子啊~~~
16. new delete malloc free的关系
- 由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free
- 因此C++语言需要一个能完成动态内存分配和初始化工作的运算符new,以及一个能完成清理与释放内存工作的运算符delete。注意new/delete不是库函数。
- delete会调用对象的析构函数,和new对应free只会释放内存,new调用构造函数。malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符。它们都可用于申请动态内存和释放内存
delete只会调用一次析构函数,而delete[]会调用每一个成员的析构函数
delete与New配套,delete []与new []配套
17.定义一个对象时先调用基类的构造函数、然后调用派生类的构造函数;析构的时候恰好相反:先调用派生类的析构函数、然后调用基类的析构函数
18.
多态:是对于不同对象接收相同消息时产生不同的动作。C++的多态性具体体现在运行和编译两个方面:
在程序运行时多态性通过继承和虚函数来体现;
在程序编译时多态性体现在函数和运算符的重载上
虚函数:在基类中冠以关键字 virtual 的成员函数。 它提供了一种接口界面。允许在派生类中对基类的虚函数重新定义
纯虚函数:在基类中为其派生类保留一个函数的名字,以便派生类根据需要对它进行定义。作为接口而存在 纯虚函数不具备函数的功能,一般不能直接被调用。
从基类继承来的纯虚函数,在派生类中仍是虚函数。如果一个类中至少有一个纯虚函数,那么这个类被称为抽象
抽象类中不仅包括纯虚函数,也可包括虚函数。抽象类必须用作派生其他类的基类,而不能用于直接创建对象实例。但仍可使用指向抽象类的指针支持运行时多态性