C++学习笔记



转自:http://blog.chinaunix.net/uid-20196318-id-2420689.html

以前学C++时记的比较,因最近开发用C++较多,把笔记翻出来复习了一下,跟大家分享一下。


类的声明及定义

1.  classstructunion保留字都可以用来声明和定义类。class中成员默认为private类型,structunionC语言兼容,成员默认为public类型。

2.  只有当类没有显式的定义构造/析构函数时,C++才会提供默认的构造/析构函数;默认的构造函数只负责创建对象,不做任何初始化工作。

3.  程序正常退出时,析构函数会被隐式调用;非正常退出(如abort)则析构函数不会被调用,可能导致系统资源没有及时得到回收。构造函数只能被隐式调用,析构函数可以被显式调用。

4.  对象在退出其作用域时自动析构,其对象的析构顺序与其创建的顺序相反;常量对象在创建之后立即析构。


类成员的访问权限

1.  private说明的对象成员是完全私有的,即便是派生类的后代对象也不能访问这类成员。

2.  protected说明的对象成员是私有的,受保护的,该对象派生的后代可以访问这类成员。

3.  public说明的对象成员是完全公开的,任何对象都能访问这类成员。

4.  无论什么类型的的对象成员,都可以被友元函数访问。

5.  类的访问权限只能防止无意识的越权访问,通过强制类型转换,可对类的成员无限制的进行访问。


内联函数

1. 不管是否出现inline保留字,在类体内定义的任何函数成员都会自动成为内联函数。

2. 在类题外定义内联函数,必须用inline显式的加以说明。

3. 内联函数的定义必须出现在内联函数第一次调用之前,否则以普通形式调用(内联失败)。


new delete

1. 对于简单类型以及没有定义构造和析构函数的类,malloc/freenew/delete两种内存分配方式可以混用;若类定义了构造函数和析构函数,则最好使用newdelete来分配和释放内存。

2. 在用new为数组分配空间时,数组的第一维下标可以是动态的,其它维则要求是静态的,即必须为整型常量或常量表达式;如果数组元素的类型为类,且希望用new创建对象数组,则相应的类必须定义无参数的构造函数,如果没有定义任何构造函数则使用C++的无参数构造函数。

3. 在全局空间重载newdelete运算符,则全局空间中的使用newdelete将是重载版本。

4. 在类空间重载newdelete运算符,则对于该类的newdelete将使用类的重载版本。

5. delete不需要测试指针是否为0,因为在delete的实现中已经考虑到了,没有必要进行重复的测试。


隐含的 this指针

1. 类的普通成员函数比静态成员函数多了一个隐含参数this指针,隐含this指针是普通成员函数的第一个参数,该参数的类型为指向此类对象的const指针。

2. this可以用来区别与该函数成员参数同名的数据成员。

3. this可以用来访问调用该函数成员的对象、对象的地址和对象的引用。

4. 在非const成员函数中,const的声明如:C * const this;

const成员函数中,const的声明如:const C * const this;


对象初始化

1.  若类定义了构造函数,则其对象必须用类定义的构造函数进行初始化;当类含有只读和引用类型的非静态数据成员时,类必须为这些成员定义构造函数。

2.  假定数据成员类A包含B类的非静态数据成员,如果B类定义了带参数的构造函数,则A类必须定义自己的构造函数,不能使用C++缺省的构造函数。

3.  构造函数必须初始化对象的对象成员,只读成员和引用成用,且只能在构造函数的函数体前初始化一次;其他数据成员可以在构造函数的函数体前初始化,也可以在构造函数的函数体内再次初始化。

4.  数据成员按其在类中定义的顺序初始化,而与他们出现在构造函数体前的顺序无关。如果简单的类型数据成员没有出现在构造函数的函数体前,则他们的值将被缺省的初始化为0

5.  在定义的时候使用A a = A()时,与A a()一样,只调用构造函数,不调用operator=


名字空间

1. namespace保留字用于定义名字空间。名字空间必须在程序的全局作用域内定义,不能在函数内定义,最外层名字空间的名称必须在程序的全局作用域内唯一,名字空间可分多次定义。没有名称的名字空间称为匿名名字空间,每个程序只能有一个匿名名字空间。

2. using保留字用于声明程序要引用的名字空间成员,或者用于指示程序要引用的名字空间。如using A::x,则将x引入到了代码所在的作用域,不能再重复定义x;而如果使用using namespace A,则仍可定义x,但须按照A::X才能访问到A中的x

3. 名字空间可以定义别名,以代替过长和难懂的名字空间名称,如namespace ABCD=A::B::C::D,则以后直接可以用ABCD来访问多重名字空间。


constvolatilemutable

1. 使用const声明不可变的数据成员,函数成员的参数和返回值等,包含const成员的类必须定义构造函数。

2. volatile修饰的变量表示其可能被并发访问(修改),该保留字告诉编译器不要对变量的访问做任何访问优化,即不利用寄存器存放中间计算结果,直接访问对象以便获得对象的最新值。

3. 普通函数成员的参数表后可以出现constvolatile,其修饰的是函数成员隐含参数this指针指向的对象。

4. mutable修饰的数据成员是易变的,mutable成员总可以被更新,即使在const类型的成员函数中。


引用

1. 引用时变量的别名,可以通过别名直接访问被引用的变量;而指针变量的值是变量的地址,指针是通过地址间接访问变量的值。

2. 引用必须被初始化,且初始化之后不能再做其他变量的引用(别名),引用参数则在函数调用时进行初始化。

3. 引用可用于做函数的参数或返回值,避免了传递参数时大量数据的拷贝。

4. 在目标代码中,引用是不存在的,需要使用引用的地方,已经尤其引用的对象替代了。


引用对象

1. 引用变量是对引用变量的别名,对被引用的变量必须进行构造和析构,而引用变量本身没有必要构造和析构。

2. 普通引用变量必须用左值初始化,如果用右值表达式进行初始化,就会生成一个临时的匿名变量,引用参数也一样;如A &q = new A(3),则在使用完q后必须delete &q,以释放临时匿名变量的空间。

3. 非引用类型的形参是作用域限于函数的局部变量,形参对象的析构是在函数调用返回前完成的,至于形参对象的构造则是在调用时由值参数传递的,值参数传递将实参各数据成员的值相应地赋给形参的数据成员,对于指针类型的数据成员则只复制指针的值,而没有复制指针所指向的存储单元,即进行浅拷贝。如果类中含有指针成员,则进行浅拷贝可能导致内存错误,必须定义拷贝构造函数,在函数调用时使用拷贝构造函数进行深拷贝。


静态数据成员

1. 静态数据成员用于描述类的总体信息,必须在类的体外进行定义并初始化。

2. 静态数据成员脱离具体对象独立存在,其存储单元不是任何对象存储空间的一部分,但逻辑上所哟对象都共享这一存储单元,在计算对象或类的存储空间时不能包含静态数据成员。

3. 静态数据成员描述类的总体信息,由于全局类作用与所有程序文件,故全局类的静态数据成员也必须作用于所有程序文件,即定义的时候是int P::q = 0,而不是static intP::q = 0,但在类中声明时要加上static

4. union的数据成员必须共享存储空间,而静态数据成员各自独立分配存储单元,故静态数据成员不能成为union的成员。

5. 静态数据/函数成员可通过三种方式访问:

(1) A::member (2) a.A::member (3) a.member


静态函数成员

1. 普通成员函数的第一个参数为隐含this指针,而静态函数成员没有隐含的this参数。

2. 构造函数、析构函数、虚函数等有this指针,若函数成员的参数表后出现constvolatile,则该函数成员的参数表必包含隐含的this指针,这些函数不能定义为静态函数成员。

3. union不能定义静态数据成员,但可以定义静态函数成员。


C转向C++

1.  尽量用<iostream>而不用<stdio.h>

3.  一个对象以值传递的方式传入函数体

2.  标示,能匹配任意异常)或是类型确定的参数。

7. 异常处理按catch块的顺序匹配,基类异常对象能匹配派生类对象,省略参数的catch块能匹配任意异常;故通常将派生类的catch块放到基类之前,省略参数的catch块放到最后。

8. 异常接口声明的异常有该函数引发,而其自身又不想捕获和处理的异常,异常接口定义的异常出现在函数参数表的后面,用throw列出要引发的异常类型。如:

void anyexception();  // 可引发任何异常

void noexception() throw(); // 不引发任何异常

void noexpected() throw(A,B); // 引发异常AB

声明异常接口时,函数声明与定义的异常声明接口要一致,在函数声明时throw(A),则在函数定义时也许指定throw(A)


C++标准库

1. 标准化过程中,C++生成新头文件的方法仅仅是将现有C++头文件名中的 .h 去掉,方法本身不重要,正如最后产生的结果不一致也并不重要一样。所以<iostream.h>变成了<iostream><complex.h>变成了<complex>,等等。对于C 头文件,采用同样的方法,但在每个名字前还要添加一个c。所以C <string.h>变成了<cstring><stdio.h>变成了<cstdio>,等等。最后一点是,旧的C++头文件是官方所反对使用的(即,明确列出不再支持),但旧的C 头文件则没有(以保持对C 的兼容性)。实际上,编译器制造商不会停止对客户现有软件提供支持,所以可以预计,旧的C++头文件在未来几年内还是会被支持。

2. 旧的C++头文件名如<iostream.h>将会继续被支持,尽管它们不在官方标准中。这些头文件的内容不在名字空间std 中。

3. 新的C++头文件如<iostream>包含的基本功能和对应的旧头文件相同,但头文件的内容在名字空间std 中。(在标准化的过程中,库中有些部分的细节被修改了,所以旧头文件和新头文件中的实体不一定完全对应。)

4. 标准C 头文件如<stdio.h>继续被支持。头文件的内容不在std 中。

5. 具有C 库功能的新C++头文件具有如<cstdio>这样的名字。它们提供的内容和相应的旧C 头文件相同,只是内容在std 中。


派生权限控制

 

私有继承private

保护继承protected

公有继承public

private

不可访问

不可访问

不可访问

protected

private

protected

protected

public

private

protected

public

1. 公有继承被称为“类型继承”,派生类是基类的子类型。

2. 私有继承被称为“实现继承”,派生类不直接支持基类的公有接口,相反,当其提供自己的接口时,它希望重用基类的实现(组合也能达到这个目的,视情况而定)。

3. 保护继承主要用于多层次的继承。

4. 常见的多继承模式为:继承一个类的公有接口和另一个类的实现。

派生类的构造顺序

1. 调用虚基类的构造函数,无论虚基类出现在继承层次上的哪个位置,它们都先于非虚基类被构造。

2. 调用基类的构造函数,按继承列表中出现的顺序。

3. 按照数据成员的声明顺序,依次调用数据成员的构造函数或初始化数据成员。

4. 执行派生类构造函数的函数体。

5. 析构顺序与构造过程相反。


C++ 对多态的支持

1. 通过一个隐式转换,从“派生类的指针或引用”转换到“其共有基类类型的指针或引用”。

2. 通过虚函数机制。

3. 通过dynamic_casttypeid实现从基类指针向派生类指针的转换。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值