C++基础学习总结

第一章 认识C++对象

  1. 一般称现实世界中客观存在的事物为对象;
  2. C++语言兼容C语言;
  3. .cpp作为文件扩展名,.h作为标识头文件;
  4. /*注释直到*/结束,//至本行结束;
  5. 提取操作符>>,输入对象 cin;插入操作符<<,输出对象cout
  6. 标准输入输出库的头文件是iostream,使用方法:#incluede <iostream>
  7. endl\n换行;
  8. 使用命名空间:using namespace std;
  9. 对象的定义及初始化:
int z(0);	//等同于int z=0;
int b(50);	//等同于int b=0;
  1. 函数原型及其返回值:函数都需要有类型说明。int main() 指出main是整数类型,返回值由return后面的表达式决定,且表达式的值必须与声明函数的类型一致。
  2. C++函数有:库(标准)函数和自定义函数;
  3. 严格检查调用函数是否匹配,应使用函数原型声明;
  4. C++使用变量的基本规则是:必须先声明,后使用,对函数调用也是如此。
  5. C语言一般使用"#define"定义常量,在C++中,建议使用const代替宏定义。
  6. C++语言可以使用宏定义。无参数的宏作为常量,而参数的宏则可以提供比函数更高的效率。
  7. 被const修饰的变量的值在程序中不能被改变,所以在声明符号常量是,必须对符号常量进行初始化,除非这个变量使用extern修饰的外部变量。
const int i=8;			//正确
const int d;			//错误
extern const int d;		//正确
  1. 预处理语句有3种,分别是宏定义、文件包含和条件编译。
    const #define PI 3.14159
        
    #include "filename"
    #include <filename>    
  1. 为同一个函数定义几个版本,从而使一个函数名具有多种功能,称为函数重载;

  2. 数据类型长度(字节)
    int4

    int 和short至少16位,long至少32位,short不能长于int,int不能长于long

  3. 整数常量:十进制常量、长整型常量(后缀L或l),八进制常量(零),十六进制常量(0x);

  4. 动态分配内存:new 类型名 [size]指针名=new 结构名delete 指针名

  5. 引用就是将一个新标识符合一块已经存在的存储区域相关联。

  6. 不能直接声明对数组的引用,也不能声明引用的引用;

  7. const限定符强制改变访问权限;

const int *p;	//指向常量的指针,“*p”是常量,不能将“*p”作为左值进行操作,即限定了“*p=”的操作
int * const p=&x;	//常量指针
const int * const p=&x;	//指向常量的常量指针
  1. 常量指针:不能改变p的指向,但可以通过间接引用运算符“*”改变其值,例如语句“*p=56;”将上面的x的值改变为56。

  2. 指向常量的常量指针:声明指针和指向的对象都不能改动的“指向常量的常量指针”,这时必须要初始化指针。int x=2;

    const int * const p=&x;

    告诉编译时,*p和p都是常量,都不能作为左值。

  3. 泛型算法,就是提供的操作与元素的类型无关。

  4. 对数组操作,需要包含头文件<algorithm>,对数组进行降幂排序和排序,需要包含头文件<functional>

  5. 数组操作示例

    操作示例
    反转reverse(a,a+Len);
    复制copy(a,a+Len,b); reverse_copy(a,a+Len,b);
    升幂sort(a,a+Len);
    降幂sort(b,b+Len,greater());
    查找find(a,a+Len,value);
    输出copy(a,a+Len,ostream_iterator( cout,“字符串”));
  6. 数据的简单输入输出格式,C++提供了两种格式控制方式:一种是使用ios _base类提供的接口;另一种是使用一种称为操控符的特殊函数,它的特点是可直接包含在输出和输入的表达式中,因此更为方便,不带形式参数的操控符定义在头文件<iostream>中,带形式参数的操控符定义在头文件<iomanip>中。

名称含义
dec转为十进制
oct转为八进制
hex转换为十六进制
endl输出一个换行符并刷新流
resetionsflags清楚flag指定的标志位
setionsflags设置flag指定的标志位
setfill设置ch为填充字符
setprecision设置浮点数输入精度n
setw设置输入数据字段宽度
  1. 用C++语言写成的程序称为源程序,源程序必须经过C++编译程序翻译成机器语言才能执行。要得到一个用C++语言设计的、名为myapp.exe的可执行文件,其过程可分为如下几步:
  1. 先使用编辑器编辑一个C++程序mycpp.cpp,又称其为C++的源程序。
  2. 然后使用C++编译器对这个C++程序进行编译,产生文件mycpp.obj
  3. 再使用连接程序(又称Link),将mycpp.obj变成mycpp.exe
  1. 集成环境,就是将C++语言编辑、编译、连接和运行程序都集成到一个综合环境中。

第二章 从结构到类的演变

  1. 没有使用private定义的成员函数,默认为public。

  2. 类使用关键字class定义,默认的是private。

  3. “面向过程”,就是不必了解计算机的内部逻辑,而把精力主要集中在对如何求解问题的算法和过程的描述上,通过编写程序把解决问题的步骤告诉计算机。

  4. 函数,就是模块的基本单位,是对处理问题的一种抽象。

  5. 结构化程序设计使用的是功能抽象,面向对象程序设计不仅能进行功能抽象,而且能进行数据抽象。“对象”实际上是功能抽象和数据抽象的统一。

  6. 软件开发是对给定问题求解的过程。从认识论的角度看,可以归为两项主要的活动:认识与描述。

  7. 面向对象的程序设计具有抽象、封装、继承和多态性等关键要素。

  8. C++可使用对象名、属性和操作三要素来描述对象。

  9. 人们主要使用由特殊到一般的归纳法和由一般到特殊的演绎法。在归纳的过程中,是从一个个具体的事物中把共同的特征抽取出来,形成一个一般的概念,这就是“归类”;在演绎的过程中,把同类事物,根据不同的特征分成不同的小类,这就是“分类”。对于一个具体的类,它有许多具体的个体,这些个体叫做“对象”。

  10. 类的作用是定义对象。

  11. 将类封装起来,也是为了保护类的安全。所谓安全,就是限制使用类的属性和操作。

  12. 对象内部数据结构这种不可访问性称为信息(数据)隐藏。

  13. 继承是一个类可以获得另一个类的特性的机制,继承支持层次概念。

  14. 不同的对象可以调用相同名称的函数,但可导致完全不同的行为的现象称为多态性。

  15. 使用string类定义存储字符串的对象,#include <string>

    string str='A';		//错误
    string str('A')		//错误
    string str="'A";	//正确
    str[0]='a';			//√
    
  16. 对象名.成员函数:

    对象名称.find(要查找的字符串,开始查找的位置);返回查找到的字符串在主串的位置。找不到,返回值为-1.

    str1.size()单词长度

  17. C++标准程序库提供complex类定义复数对象。头文件:#include<complex>

    complex num1(2,3);

  18. 类是抽象出一类物质的共同特征,模板则是归纳出不同类型事物的共同操作。

  19. swap成员函数用来交换两个数组分量。

第三章 函数和函数模板

  1. C++函数还可以使用传递对象的“引用”方式,即它的函数参数有两种传递方式:传值和传引用。

    传引用其实就是传对象的地址,也称传地址方式。

  2. 参数传递中不要混淆传地址值和传地址的区别。传地址值传递的是值,不是地址;传地址传的是地址不是地址值。传递对象地址值是使用对象指针做为参数;传递地址时使用对象引用作为参数。

  3. 使用值传递方式将实参传给形参,形参是实参的备份

  4. 将对象作为函数参数:是将实参对象的值传递给形参对象,这种传递是单向的。形参拥有实参的备份,当在函数中改变形参的值时,改变的是这个备份中的值,不会影响原来实参的值。

  5. 对象指针作为函数参数:将指向对象的指针作为函数参数,形参是对象指针(指针可以指向对象的地址),实参是对象的地址值。实参和形参地址相同,改变形参就是改变实参。

  6. 引用作为函数参数:可以使用“引用”作为函数的参数(引用形参)。这时函数并没有对形参对象初始化,即没有指定形参对象是哪个对象的别名。在函数调用是,实参对象名传给形参对象名,形参对象名就成为实参对象名的别名。实参对象和形参对象代表同一个对象,所以改变形参对象的值就是改变实参对象的值。

  7. 默认参数是不要求程序员设定该参数,而由编译器在需要时给该参数赋默认值。当程序员需要传递特殊值时,必须显式地指明。默认参数是在函数原型中说明的,默认参数可以多于1个,但必须放在参数序列的后部。

  8. 一个默认参数需要指明一个特定值,则在其之前所有的参数都必须赋值。

  9. 用const修饰传递参数,意思是通知函数,它只能使用参数而无权修改它。这主要是为了提高系统的自身安全。

  10. C++函数的返回值类型可以是除数组以外的任何类型。非void类型的函数必须向调用者返回一个值。

  11. 数组只能返回地址。当函数返回值是指针或引用对象时,需要特别注意:函数返回所指的对象必须继续存在,因此不能将函数内部的局部对象作为函数的返回值。

  12. 返回引用的函数:函数可以返回一个引用,将函数说明为返回一个引用的主要目的是为了将该函数用在赋值运算符的左边。函数原型的表示方法如下:

    数据类型 &函数名(参数列表);

  13. 返回指针的函数:函数的返回值可以是存储某种类型数据的内存地址,称这种函数为指针函数。它们的一般定义形式如下:

    类型标识符 *函数名(参数列表);

  14. 在C++中,除了内存分配失败之外,new不会返回空指针,并且没有任何对象的地址为零。

  15. 返回对象的函数:用函数返回值作为另一个函数的参数,这个返回值必须与参数类型一致。

  16. 使用关键字inline说明的函数称内联函数。

  17. 在C++中,除具有循环语句、switch语句的函数不能说明为内联函数外,其他函数都可以说明为内联函数。

  18. 使用内联函数能加快程序执行速度,但如果函数体语句多,则会增加程序代码的大小。

  19. 函数重载可以使一个函数名具有多种功能,即具有“多种形态”,这种特性称为多态性。参数类型不同,参数个数不同,函数名相同,参数列表不同。

  20. C++的多态性又被直观地称为“一个名字,多个函数”。源代码只指明函数调用,而不说明具体调用哪个函数。编译器的这种连接方式称为动态联编或迟后联编。在动态联编中,直到程序运行才能确定调用哪个函数(动态联编需要虚函数的支持)。如果编译器在编译时,能根据源代码调用固定的函数标识符,并用物理地址代替它们,这就称为静态联编或先期联编。静态联编是在程序被编译时进行的。

  21. 函数模版:当用实际的类型来实例化这种函数时,就好像按照模版来制造新的函数一样,所以称这种函数为函数模板。将函数模版与某个具体数据类型连用,就产生了模板函数,又称这个过程为函数模板实例化,这种形式就是类型参数化。

  22. 使用显式规则和关键字typename,C++专门定义一个仅仅用在模板中的关键字typename,它的用途之一是代替template参数列表中的关键字class。

template <class T>
T max(T m1,T m2)
    
template <typename T>
T max(T m1,T m2)

第四章 类和对象

  1. 类是具有惟一标识符的实体;在类中声明的任何成员不能使用extern、auto和register关键字进行修饰;

  2. 类中声明的变量属于该类,在某些情况下,变量也可以被该类的不同实例所共享。

  3. 类和其他数据类型不同的是,组成这种类型的不仅可以有数据,而且可以有对数据进行操作的函数,他们分别叫做类的数据成员和类的成员函数,而且不能在类声明中对数据成员使用表达式进行初始化。

  4. 类声明以关键字class开始,其后跟类名。类所声明的内容用花括号括起来,右花括号后的分号作为类关键字声明语句的结束标志。这一对花括号之间的内容称为类体;

  5. 访问权限用于控制对象的某个成员在程序中的可访问性,如果没有使用关键字,则所有成员默认声明为private权限。

  6. 定义成员函数的一般形式如下:

返回类型 类名::成员函数名(参数列表)
{
成员函数的函数体//内部实现
}
//其中“::”是作用域运算符,“类名”是成员函数所属类的名字,“::”用于表名其后的成员函数是属于这个特定的类。换言之,“类名::成员函数名”的意思就是对属于“类名”的成员函数进行定义,而“返回类型”则是这个成员函数返回值的类型。


7. 使用关键字inline将成员函数定义为内联函数。在声明类的同时,在类体内给出成员函数的定义,则默认为内联函数。
8. 数据成员的赋值:不能在类体内给数据成员赋值。在类体外就更不允许了。

```c++
Class Point{
 int x=25,y=56 	//×
}
  1. 使用类的对象:对象和引用都使用运算符“.”访问对象的成员,指针则使用“- >”运算符。

(1)类的成员函数可以直接使用自己类的私有成员(数据成员和成员函数)

(2)类外面的函数不能直接访问类的私有成员(数据成员和成员函数)

(3)类外面的函数只能通过类的对象使用该类的公有成员函数。

  1. 在程序运行时,通过为对象分配内存来创建对象。在创建对象时,使用类作为样板,故称对象为类的实例。

  2. 定义类对象指针的语法如下:

    //类名* 对象指针名;
    
    //对象指针名=对象的地址;
    
    //可以直接进行初始化:类名* 对象指针名=对象的地址;
    
    //类对象的指针可以通过“->”运算符访问对象的成员,即:对象指针名->对象成员名
    
  3. C++有称为构造函数的特殊成员函数,它可自动进行对象的初始化。

  4. 当没有为一个类定义任何构造函数的情况下,C++编译器总要自动建立一个不带参数的构造函数。

  5. 一旦程序定义了自己的构造函数,系统就不再提供默认构造函数。

  6. 构造函数的名字应与类名同名。并在定义构造函数时不能指定返回类型,即使void类型也不可以。

  7. 类的构造函数可以在类体内声明时定义或类体外定义。形式:

    类名::类名(形参1,形参2,。。。形参n):x1(形参1),x2(形参2),。。。xn(形参n){}
    
    类名::类名(形参1,形参2,。。。形参n){
        x1=形参1;
    	x2=形参2;
        xn=形参n;
    }
    
  8. 为每一个数组元素调用一次构造函数。

  9. 程序员不能在程序中显式地调用构造函数,构造函数是自动调用的。例如构造一个Point类的对象a,不能写成“Point a.Point(x,y) ;”,只能写成“Point a(x,y) ;”。编译系统会自动调用Point(x,y)产生对象a并使用x和y将其正确地初始化。

  10. 运算符new用于建立生存期可控的对象,new返回这个对象的指针。由于类名被视为一个类型名,因此,使用new建立动态对象的语法和建立动态变量的语法类似,其不同点是new和构造函数一起使用。

  11. 使用new建立的动态对象只能用delete删除,以便释放所占空间。

  12. 如果程序定义自己的有参数构造函数,又想使用无参数形式的构造函数,解决的方法时间相应的构造函数全部使用默认的参数设计。

  13. 在通常情况下,编译器建立一个默认复制构造函数,默认复制构造函数采用拷贝方式使用已有的对象来建立新对象,所以又直译为拷贝构造函数。程序员可以自己定义复制构造函数,对类A而言,复制构造函数的原型如下:A::A(A&) 。

    为了不改变原有对象,更普通的形式是像下面这样使用const限定:A::A(const A &)

    像调用构造函数一样,如果自定义了复制构造函数,编译器只调用程序员为它设计的赋值构造函数。Point(Point &);

  14. 在C++中,在一个类中定义的成员函数可以访问该类任何对象的私有成员。

  15. 复制构造函数必须使用对象的引用作为形式参数。

  16. 在对象消失时,应使用析构函数释放由构造函数分配的内存。

  17. 构造函数、赋值构造函数和析构函数是构造型成员函数的基本成员。

  18. 最容易、也最符合逻辑的方法是指定这个函数的名称与类名一样。在析构函数的前面加上一个~号(仍然称析构函数与类同名)。

  19. 在定义析构函数时,不能指定任何返回类型,即使指定void类型返回类型也不行。析构函数也不能指定参数,但是可以显示地说明参数为void,即形如A::~A(void)。

  20. 从函数重载的角度分析,一个类也只能定义一个析构函数且不能指明参数,以便编译系统自动调用。

  21. 析构函数在对象的生存期结束时被自动调用。当对象的生存期结束时,程序为这个对象调用析构函数,然后回收这个对象占用的内存。

  22. 全局对象和静态对象的析构函数在程序运行结束之前调用。

  23. 类的对象数组的每个元素调用一次析构函数。全局对象数组的析构函数在程序结束之前被调用

  24. 运算符delete与析构函数一起工作。当使用运算符delete删除一个动态对象时,首先为这个动态对象调用析构函数,然后再释放这个动态对象占用的内存,这和使用new建立动态对象的过程正好相反

  25. 当使用delete释放动态对象数组时,必须告诉这个动态对象数组有几个元素对象,C++使用“[ ]”来实现。即语句:delete[ ] ptr ; //注意不要写错为delete ptr[]

  26. 如果在定义类时没有定义析构函数,C++编译器也为它产生一个函数体为空的默认析构函数。

  27. 使用this指针,保证了每个对象可以拥有自己的数据成员,但处理这些数据成员的代码可以被所有的对象共享。

  28. C++规定,当一个成员函数被调用是,系统自动向它传递一个隐含的参数,该参数是一个指向调用该函数的对象的指针,从而使成员函数知道该对哪个对象进行操作。在程序中,可以使用关键字this来引用该指针。

  29. this指针是C++实现封装的一种机制,它将对象和该对象调用的成员函数连接在一起,在外部看来,每一个对象都拥有自己的成员函数。

  30. 除非有特殊需要,一般情况下都省略符号“this ->”,而让系统进行默认设置。

  31. 对象的性质:

    (1)同一个类的对象之间可以相互赋值。

    (2)可使用对象数组。

    (3)可使用指向对象的指针,使用取地址运算符&将一个对象的地址置于该指针中。

    注意,指向对象的指针的算术运算规则与C语言的一样,但指向对象的指针不能取数据成员的地址,也不能去成员函数的地址。

    (4)对象可以用作函数参数。

    (5)对象作为函数参数时,可以使用对象、对象引用和对象指针。

    (6)一个对象可以做为另一个类的成员。

  32. 使用类的权限

    (1)类本身的成员函数可以使用类的所有成员(私有和公有成员)。

    (2)类的对象只能访问公有成员函数。

    (3)其他函数不能使用类的私有成员,也不能使用公有成员函数,它们只能通过类的对象使用类的公有成员函数。

    (4)虽然一个可以包含另外一个类的对象,但这个类也只能通过被包含类的对象使用那个类的成员函数,通过成员函数使用数据成员。

  33. 不完全的类声明:类不是内存中的物理实体,只有当使用类产生对象时,才进行内存分配,这种对象建立的过程称为实例化。应当注意的是:类必须在其成员使用之前先进行声明。

    class MembersOnly; //不完全的类声明

    MenbersOnly *club; //定义一个全局变量类指针

    第一条语句称为不完全类声明,它用于在类没有完全定义之前就引用该类的情况。

    不完全声明的类不能实例化,否则会出现编译错误;不完全声明仅用于类和结构,企图存取没有完全声明的类成员,也会引起编译错误。

  34. 空类:尽管类的目的是封装代码和数据,它也可以不包括任何声明。class Empty{};

  35. 类作用域:声明类时所使用的一对花括号形成所谓的类的作用域。在类作用域中声明的标识符只在类中可见。

如果该成员函数的实现是在类定义之外给出的,则类作用域也包含类中成员函数的作用域。

类中的一个成员名可以使用类名和作用域运算符来显式地指定,这称为成员名限定。

  1. 只有定义和描述了对象之间的关系,各个对象才能构成一个整体的、有机的系统模型,这就是对象的结构和连结关系。

  2. 对象结构是指对象之间的分类(继承)关系和组成(聚合)关系,统称为关联关系。

  3. 对象之间的静态关系是通过对象属性之间的连接反映的,称为实例连接。

  4. 对象行为之间的动态关系是通过对象行为(信息)之间的依赖关系表现的,称之为消息连接。

  5. 实例连接和消息连接统称为连接。

  6. 组成关系说明的结构是整体与部分关系。

    C++中最简单的是包含关系。

    C++语言中的“聚合”隐含了两种实现方式,第一种方式是独立地定义,可以属于多个整体对象,并具有不同生存期。这种所属关系是可以动态变化的,称之为聚集。使用空心菱形表示它们之间的关系。第二种方式是用一个类的对象作为一种广义的数据类型来定义整体对象的一个属性,构成一个嵌套对象。在这种情况下,这个类的对象只能隶属于惟一的整体对象并与它同生同灭,称这种情况为“组合”,它们之间的关联关系比第一种强,具有管理组成部分的责任,使用实心菱形表示。

  7. 实例连接反映对象之间的静态关系,例如车和驾驶员的关系,这种双边关系在实现中可以通过对象(实例)的属性表达出来。实例连接有一对一、一对多、多对多3种连接方式。

  8. 消息连接描述对象之间的动态关系。即若一个对象在执行自己的操作时,需要通过消息请求另一个对象为它完成某种服务,则说第一个对象与第二个对象之间存在着消息连接。消息连接是有方向的,使用一条带箭头的实线表示,从消息的发送者指向消息的接收者。

  9. 对象传送的消息一般由3部分组成:接收对象名、调用操作名和必要的参数。

  10. 对象的属性是指描述对象的数据成员。数据成员可以是系统或程序员定义的数据类型。对象属性的集合称为对象的状态。

  11. 对象的行为是定义在对象属性上的一组操作的集合。操作(函数成员)是响应消息而完成的算法,表示对象内部实现的细节。对象的操作集合体现了对象的行为能力。

  12. 对象的属性和行为是对象定义的组成要素,分别代表了对象的静态和动态特征。

  13. 一般要求将类的声明放在头文件中,非常简单的成员函数可以在声明中定义(默认内联函数形式),实现放在.cpp文件中。在.cpp文件中,将头文件包含进去。主程序单独使用一个文件,这就是多文件编程规范。

  14. 嵌入指令#include指示编译器将一个源文件嵌入到带有#include指令的源文件中该指令所在的位置处。尖括号或双引号中的文件名可包含路径信息。例如:#include<\user\prog.h>、

  15. 宏定义:#define指令定义一个标识符及串,在源程序中每次遇到该标识符时,编译器均用定义的串代替之。该标识符称为宏名,而将替换过程称之为宏替换。#define指令用以进行宏定义,其一般形式如下:#define 宏名 替换正文

  16. 条件编译指令是#if、#else、#elif和#endif,它们构成类似于C++的if选择结构,其中#endif表示一条指令结束。

  17. 可以在#else分支中使用编译指令#error输出出错信息。#error使用的形式如下:#error 出错信息

    “出错信息”是一个字符序列。当遇到#error指令时,编译器显示其后面的“出错信息”,并中止对程序的编。

  18. define操作符:关键字defined不是指令,而是一个预处理操作符,用于判断一个标识符是否已经被#define定义。如果标识符identifier已被#define定义,则defined(identifier)为真,否则为假。

  19. 条件编译指令#ifdef和#ifndef用于测试其后的标识符是否被#define定义,如果已经被定义,则#ifdef测试为真,#ifndef测试为假;如果没有被定义,则#ifdef测试为假,#ifndef测试为真。

第五章 特殊函数和成员

  1. 可以在一个类中说明具有某个类的类型的数据成员,这些成员成为对象成员。在类A中说明对象成员的一般形式如下:

     class A 
    
       {
    
       类名1 成员名1;
    
       类名2 成员名2;
    
       ……
    
       类名n 成员名n;
    
       };
    
    
  2. 说明对象成员是在类名之后给出对象成员的名字。为初始化对象成员,A类的构造函数要调用这些对象成员所在类的构造函数,A类的构造函数的定义形式如下:

    A::A(参数表0):成员1(参数表1),成员2(参数表2),成员n(参数表n)

    {//其他操作}

    冒号“:”后由逗号隔开的项目组成员初始化列表,其中的参数表给出了为调用相应成员所在类的构造函数时应提供的参数。参数列表中的参数都来自“参数表0”,可以使用任意复杂的表达式,其中可以有函数调用。如果初始化列表某项的参数表为空,则列表中相应的项可以省略。

  3. 对象成员构造函数的顺序取决于这些对象成员在类中说明的顺序,与他们在成员初始化列表中给出的顺序无关。析构函数的调用顺序与构造函数正好相反。

  4. 简单成员函数是指声明中不含const、volatile、static关键字的函数。

  5. 类的数据成员或成员函数使用关键字static进行修饰,这样的成员称为静态数据成员或静态成员函数,统称为静态成员。

  6. 静态数据成员只能说明一次,如果在类中仅对静态数据成员进行声明,则必须在文件作用域的某个地方进行定义。在进行初始化之前,必须进行成员名限定。

  7. 由于static不是函数中的一部分,所以在类声明之外定义静态成员函数时,不使用static。在类中定义的静态成员函数是内联的。

  8. 类中的任何成员函数都可以访问静态成员。因为静态成员函数没有this指针,所以静态成员函数只能通过对象名(或指向对象的指针)访问该对象的非静态成员。

  9. 静态成员函数与一般函数有如下不同:

    (1)可以不指向某个具体的对象,只与类名连用。

    (2)在没有建立对象之前,静态成员就已经存在。

    (3)静态成员是类的成员,不是对象的成员。

    (4)静态成员为该类的所有对象共享,它们被存储于一个公用的内存中。

    (5)没有this指针,所以除非显式地把指针传给它们,否则不能存取类的数据成员。

    (6)静态成员函数不能说明为虚函数。

    (7)静态成员函数不能直接访问非静态函数。

  10. 静态对象具有如下性质:

    (1)构造函数在代码执行过程中,第一次遇到它的时候变量定义时被调用,但直到整个程序结束之前仅调用一次。

    (2)析构函数在整个程序退出之前被调用,同样也只调用一次。

  11. 友元函数不是friend所在类的成员函数,是该类的外部函数,能够访问friend所在类的所有对象的私有、公有和保护成员。

  12. 类本身的友元函数:为本类声明一个友元函数,这时,虽然在类中说明它,但它并不是类的成员函数,所以可以在类外面像普通函数那样定义这个函数。

  13. 将成员函数用作友元:一个类的成员函数(包括构造函数和析构函数)可以通过使用friend说明为另一个类的友元。

  14. 将一个类说明为另一个类的友元:可以将一个类说明为另一个类的友元。这时,整个类的成员函数均具有友元函数的性能。声明友元关系简化为“friend class 类名;”

  15. 友元关系是不传递的,即当说明类A是类B的友元,类B又是类C的友元时,类A却不是类C的友元。

  16. 友元声明与访问控制无关。友元声明在私有区域进行或在公有区域进行是没有太大区别的。

  17. 可以在类中使用const关键字定义数据成员和成员函数或修饰一个对象。一个const对象只能访问const成员函数,否则将产生编译错误。

  18. 常量成员包括常量数据成员、静态常数据成员和常引用。静态常数据成员仍保留静态成员特征,需要在类外初始化。常数据成员和常引用只能通过初始化列表来获得初值。

  19. 常引用作为函数参数:使用引用作为参数,传送的是地址。但有时仅希望将参数的值提供给函数使用,并不允许函数改变对象的值,这时可以使用常引用作为参数。

  20. 在对象名前使用const声明常量对象,但声明时必须同时进行初始化,而且不能被更新。定义的语法如下:

    类名 const 对象名(参数表);

  21. 常成员函数:可以声明一个成员函数为const函数。一个const对象可以调用const函数,但不能调用非const成员函数。const放在函数声明之前意味着返回值是常量,但这不符合语法。必须将关键字const放在参数列表之后,才能说明该函数是一个const成员函数。

  22. 声明常成员函数的格式如下:类型标识符 函数名(参数列表) const;

    类型标识符 类名::函数名(参数列表)const{//函数体}

    类型标识符 函数名(参数列表)const{//函数体}

  23. 在定义成员函数时,函数体之前加上const可以防止覆盖函数改变数据成员的值。

  24. 在C++中声明构造函数和析构函数时使用const关键字均是非法的,但有些C++的编译程序并不给出出错信息。

  25. 编译器调用适当的构造函数建立数组的每一个分量。如果找不到合适的构造函数,则产生错误信息。

  26. 指向对象的指针是比较传统的指针,假设类A的成员函数为“void fa(void);”,如要建立一个指针pafn,它可以指向任何无参数和无返回值的类A的成员函数:void(A:? pafn)(void);从内往外看,此声明可读作:pafn是一个指针,指向类A的成员函数,此成员函数既无参数,也无返回值。

  27. 下面的例子说明了pafn如何被赋值并用以调用函数fa:

    pafn=A::fa; //指向类A的成员函数fa的指针pafn

    a x; //类A的对象x

    A *px=&x; //指向类A对象x的指针px

    (x.*pafn)(); //调用类A的对象x的成员函数fa

    (px->pafn)(); //调用类A的对象x的指针px指向的成员函数fa

  28. 指向类A中参数类型列表为list,返回类型为type的成员函数的指针声明形式如下:type(A:? pointer)(list);

  29. 如果类A的成员函数fun的原型与pointer所指向的函数的原型一样,则语句pointer=A::fun;

    将该函数的地址(这个地址不是真实地址,而是在A类中所有对象的便宜)置给了pointer。在使用指向类成员函数的指针访问对象的某个成员函数时,必须指定一个对象。用对象名或引用调用pointer所指向的函数时,使用运算符“.*”,使用指向对象的指针调用pointer所指向的成员函数时,使用运算符“->*”。

第六章 继承和派生

  1. 这种通过特殊化已有的类来建立新类的过程,叫做“类的派生”,原来的类叫做“基类”,新建立的类则叫做“派生类”。另一方面,从类的成员角度看,派生类自动地将基类的所有成员作为自己的成员,这叫做“继承”。基类和派生类又可以分别叫做“父类”和“子类”,有时也称为“一般类”和“特殊类”。

  2. 从一个或多个以前定义的类(基类)产生新类的过程称为派生,这个新类称为派生类。派生的新类同时也可以增加或者重新定义数据和操作,这就产生了类的层次性。

  3. 类的继承是指派生类继承基类的数据成员和成员函数。继承常用来表示类属关系,不能将继承理解为构成关系。

  4. C++中有两种继承:单一继承和多重继承。对于单一继承,派生类只能有一个基类;对于多重继承,派生类可以有多个基类。

  5. 声明单一继承的一般形式如下:

     class 派生类名:访问控制 基类名{
    
       private:
    
       成员声明列表
    
       protected:
    
       成员声明列表
    
       public:
    
       成员声明列表
    
       };
    
    
  6. 定义派生类的构造函数的一般形式如下:

    派生类名::派生类名(参数表0) : 基类名(参数表)

    {…//函数体}

  7. 构造函数(包括析构函数)是不被继承的,所以一个派生类只能调用它的直接基类的构造函数。当定义派生类的一个对象时,首先调用基类的构造函数,对基类成员进行初始化,然后执行派生类的构造函数,如果某个基类仍是一个派生类,则这个过程递归执行。该对象消失时,析构函数的执行顺序和执行构造函数的顺序正好相反。

  8. 使用公有方式产生的派生类成员函数可以直接访问基类中定义的或从另一个基类继承来的公有成员,但不能访问基类的私有成员。

  9. 在类的声明中,关键字protected之后声明的是类的保护成员。对派生类的成员函数而言,它是公有成员,可以被访问;而对其他函数而言则仍是私有成员,不能被访问。

  10. 在公有派生的情况下,基类成员的访问权限在派生类中保持不变。这就意味着:

    (1)基类的公有成员在派生类中依然是公有的。

    (2)基类的保护成员在派生类中依然是保护的。

    (3)基类的不可访问的和私有的成员在派生类中也仍然时不可访问的。

  11. 赋值兼容规则是指在公有派生情况下,一个派生类的对象可以作为基类的对象来使用的情况。

  12. 静态成员可以被继承,这时基类对象和派生类的对象共享该静态成员。

  13. 公有继承“就是一个(isa)”的含义。分层的意思是指“has-a(有一个)”。

  14. 私有派生,基类的私有和不可访问成员在派生类中是不可访问的,而公有和保护成员这时就成了派生类的私有成员,派生类的对象不能访问继承的基类成员,必须定义公有的成员函数作为接口。

  15. 保护派生:派生也可以使用protected。这种派生使原来的权限都降一级使用,即private变为不可访问;protected变为private;public变为protected。

  16. 一个类从多个基类派生的一般形式如下:

    class 类名1:访问控制 类名2,访问控制 类名3,…,访问控制 类名n

    {…//定义派生类自己的成员};

  17. 对基类成员的访问必须是无二义性的,如使用一个表达式的含义能解释为可访问多个基类中的成员,则这种对基类成员的访问就是不确定的,称这种访问具有二义性。

  18. 作用域分辨符和成员名限定:从类中派生其他类可能导致几个类使用同一个成员函数名或数据成员名。程序必须确切地告诉编译器使用哪个版本的数据成员或成员函数。

  19. C++可以迫使编译器“看到”当前作用域的外层部分,存取那些被隐藏的名字,这是由作用域分辨运算符“::”实现的(简称作用域运算符)。这一过程叫做作用域分辨。作用域分辨操作的一般形式如下:类名::标识符

    “类名”可以是任意基类或派生类名,“类标识符”是该类中声明的任一成员名。

  20. 派生类支配基类的同名函数:基类的成员和派生类新增的成员都具有类作用域,基类在外层,派生类在内层。如果这时派生类定义了一个和基类成员函数同名的新成员函数(因为参数不同属于重载,所以这里是指具有相同参数表的成员函数),派生类的新成员函数就覆盖了外层的同名成员函数。在这种情况下,直接使用成员函数名只能访问派生类的成员函数,只有使用作用域分辨,才能访问基类的同名成员函数。

  21. 派生类D中的名字N支配基类B中同名的名字N,称为名字支配规则。

第七章 类模板与向量

  1. 类模板声明的一般方法如下:template <类模板参数> class 类名{//类体};
  2. 用类模板定义对象的一般格式如下:

类名<模板实例化参数类型> 对象名(构造函数实参列表);

类名<模板实例化参数类型> 对象名;//默认或者无参数构造函数

  1. 在类体外面定义成员函数时,必须用template重写类模板声明。一般格式如下:template <模板参数>

    返回类型 类名<模板类型参数>::成员函数名(函数参数列表){//函数体}

  2. <模板类型参数> 是指template的“< >”内使用class(或typename)声明的类型参数,构造函数和析构函数没有返回类型。

  3. 模板实例化参数类型包括数据类型和值。编译器不能从构造函数参数列表推断出模板实例化参数类型,所以必须显式地给出对象的参数类型。

  4. 声明模板类继承之前,必须重新声明类模板。模板类的基类和派生类都可以是模板(或非模板)类。

  5. 向量是类模板,具有成员函数。

  6. 向量(vector)类模板定义在头文件vector中,它提供4种构造函数,用来定义由各元素组成的列表。用length表示长度,数据类型用type表示,对象名为name。

  7. 向量定义的赋值运算符“=”,允许同类型的向量列表相互赋值,而不管它们的长度如何。向量可以改变赋值目标的大小,使它的元素数目与赋值源的元素数目相同。

  8. 向量的第一个元素也是从0开始。

  9. 不能使用列表初始化向量,但可以先初始化一个数组,然后把数组的内容复制给向量。

  10. “与操作对象的数据类型相互独立”的算法称为泛型算法。

  11. 用iterator声明向量的正向泛型指针的一般形式如下:vector :: iterator泛型指针名;

  12. 声明逆向泛型指针使用reverse_iterator。声明的方法如下:vector<数据类型> :: reverse_iterator 指针名;

  13. 访问向量容量信息的方法

    1)size():返回当前向量中已经存放的对象的个数

    2)max_size():返回向量可以容纳最多对象的个数,一般是操作``系统的寻址空间所需容纳的对象的个数。这个参数不是用户指定的,它取决于硬件结构。

    3)capacity():返回无需再次分配内存就能容纳的对象个数。它的初始值为程序员最初申请的元素个数。当存放空间已满,又增加一个元素时,它在原来的基础上自动翻倍扩充空间,以便存放更多的元素。通俗地讲,也就是已申请的空间。这三者的关系如下。

    4)empty():当前向量为空时,返回true。

  14. 访问向量中对象的方法

    (1)front():返回向量中的第一个对象。

    (2)back():返回向量中的最后一个对象。

    (3)operator:返回向量中的第n+1个对象(下标为n的向量元素)。

  15. 在向量中插入对象的方法

    (1)push_back(const T&):向向量尾部插入一个对象。

    (2)insert(iterator it,const T&):向it所指向的向量位置前插入一个对象。

    (3)insert(iterator it,size_type n,const T&X):向it所指向量位置前插入n个值为X的对象。

  16. 在向量中删除对象的方法

    (1)pop_back(const T&):删除向量中最后一个对象。

    (2)erase(iterator it):删除it所指向的容器对象。

    (3)clear():删除向量中的所有对象,empty()返回true。

第八章 多态性和虚函数

  1. 静态联编所支持的多态性称为编译时的多态性。当调用重载函数时,编译器可以根据调用时使用的实参在编译时就确定下来应调用哪个函数。

  2. 动态联编所支持的多态性称为运行时的多态性,这由虚函数来支持。虚函数类似于重载函数,但与重载函数的实现策略不同,即对虚函数的调用使用动态联编。

  3. 静态联编中的赋值兼容性及名字支配规律:对象的内存地址空间中只包含数据成员,并不存储有关成员函数的信息。这些成员函数的地址翻译过程与其对象的内存地址无关。声明的基类指针只能指向基类,派生类指针只能指向派生。它们的原始类型决定它们只能调用各种的同名函数area。

  4. 动态联编的多态性:当编译系统编译含有虚函数的类时,将为它建立一个虚函数表,表中的每一个元素都指向一个虚函数的地址。此外,编译器也为类增加一个数据成员,这个数据成员是一个指向该虚函数表的指针,通常称为vptr。

  5. 派生类没有改写继承基类的虚函数,则函数指针调用基类的虚函数。如果派生类改写了基类的虚函数,编译器将重新为派生类的虚函数建立地址,函数指针会调用改写过的虚函数。

  6. 虚函数的调用规则是:根据当前对象,优先调用对象本身的成员函数。这和名字支配规律类似,不过虚函数是动态联编的,是在执行期“间接”调用实际上欲联编的函数。

  7. 一旦基类定义了虚函数,该基类的派生类中的同名函数也自动称为虚函数。

  8. 虚函数只能是类中的一个成员函数,但不能是静态成员,关键字virtual用于类中该函数的声明中。

  9. 当在派生类中定义了一个同名的成员函数时,只要该成员函数的参数个数和相应类型以及它的返回类型与基类中同名的虚函数完全一样,则无论是否为该成员使用virtual,它都将成为一个虚函数。

  10. 关键字virtual指示C++编译器对调用虚函数进行动态联编。这种多态性是程序运行到需要的语句处才动态确定的,所以称为运行时的多态性。不过,使用虚函数并不一定产生多态性,也不一定使用动态联编。例如,在调用中对虚函数使用成员名限定,可以强制C++对该函数的调用使用静态联编。

  11. 产生运行时的多态性有如下3个前提:

    (1)类之间的继承关系满足赋值兼容性规则。

    (2)改写了同名函数。

    (3)根据赋值兼容性规则使用指针(或引用)。

  12. 在构造函数和析构函数中调用虚函数采用静态联编,即他们所调用的虚函数是自己的类或基类中定义的函数,但不是任何在派生类中重定义的虚函数。

  13. 由于析构函数不允许有参数,因此一个类只能有一个虚析构函数。虚析构函数使用virtual说明。只要基类的析构函数被说明为虚函数,则派生类的析构函数,无论是否使用virtual进行说明,都自动地成为虚函数。

  14. delete运算符和析构函数一起工作(new和构造函数一起工作),当使用delete删除一个对象时,delete隐含着对析构函数的一次调用,如果析构函数为虚函数,则这个调用采用动态联编。一般来说,如果一个类中定义了虚函数,析构函数也应说明为虚函数,尤其是在析构函数要完成一些有意义的任务时,例如,释放内存。

  15. 如果基类的析构函数为虚函数,则在派生类为定义析构函数时,编译器所生成的析构函数也为虚函数。

  16. 在许多情况下,不能再基类中为虚函数给出一个有意义的定义,这时可以将它说明为纯虚函数,将其定义留给派生类去做。说明纯虚函数的一般形式如下:

class 类名{

virtual 函数类型 函数名(参数列表)=0;

};

  1. 一个类可以说明多个纯虚函数,包含有纯虚函数的类称为抽象类。一个抽象类只能作为基类来派生新类,不能说明抽象类的对象。但可以说明指向抽象类对象的指针(或引用)。
  2. 从一个抽象类派生的类必须提供纯虚函数的实现代码,或在该派生类中仍将它说明为纯虚函数,否则编译器将给出错误信息。这说明了纯虚函数的派生类仍是抽象类。如果派生类给了某类所有纯虚函数的实现,则该派生类不再是抽象类。
  3. 如果通过同一个基类派生一系列的类,则将这些类总称为类族。抽象类的这一特点保证了进度类族的每个类都具有(提供)纯虚函数所要求的行为,进而保证了围绕这个类族所建立起来的软件能正常运行,避免了这个类族的用户由于偶然失误而影响系统正常运行。
  4. 抽象类至少含有一个虚函数,而且至少有一个虚函数是纯虚函数,以便将它与空的虚函数区分开来。下面是两种不同的表示方法:

virtual void area()=0;

virtual void area(){}

  1. 在成员函数内可以调用纯虚函数。因为没有为纯虚函数定义代码,所以在构造函数或虚构函数内调用一个纯虚函数将导致程序运行错误。
  2. 在派生类中,当一个指向基类成员函数的指针指向一个虚函数,并且通过指向对象的基类指针(或引用)访问这个虚函数时,仍发生多态性。

第9章 运算符重载及流类库

  1. 编译器在默认情况下为每个类生成一个默认的赋值操作,用于同类的两个对象之间相互赋值。默认的含义是逐个为成员赋值,即将一个对象的成员的值赋给另一个对象相应的成员,这种赋值方式对于有些类可能是不正确的。

  2. C++的关键字“operator”和运算符一起使用就表示一个运算符函数。例如“operator +”表示重载“+”运算符。

  3. C++的运算符大部分都可以重载,不能重载的只有 . 、:: 、* 和 ? : 。前面三个是因为在C++中都有特定的含义,不准重载以避免不必要的麻烦;“?:”则是因为不值得重载。另外,“sizeof”和“#”不是运算符,因而不能重载,而=、()、[ ] 、->这4个运算符只能用类运算符来重载。

  4. 插入符“<<”和提取符“>>”的重载也与其他运算符重载一样,但操作符的左边是流对象的别名而不是被操作的对象,运算符跟在流对象的后面,它们要直接访问类的私有数据,而且流是标准类库,用户只能继承不能修改,更不能是流库的成员,所以它们必须作为类的友元重载。

  5. 插入符函数的一般形式如下:

    ostream &operator<<(ostream & output,类名 &对象名)
    {
    	return output;	//output是类ostream对象的引用,它是cout的别名,即ostream&output=cout
    }
    
  6. 提取符函数的一般形式如下:

    istram &operator>>(istream & input,类名&对象名)
    {
    	return input;	//input是类istream对象的引用。它是cin的别名,即istream&input=cin。调用参数时,input引用cin(即cin的别名)
    }
    
  7. 运算符“[ ]”只能用类运算符来重载。

  8. C++的输出操作将一个对象的状态转换成一个字符序列,输出到某个地方。

  9. 输入操作也是从某个地方接收到一个字符序列,然后将其转换成一个对象的状态所要求的格式。

  10. 从ios类公有派生的istream和ostream两个类分别提供对流进行提取操作和插入操作的成员函数,而iostream类通过组合istream类和ostream类来支持对一个流进行双向(也就是输入和输出)操作,它并没有提供新的成员函数。

  11. C++流类库预定义了4个流,它们是cin、cout、cerr、clog。

  12. 将cin视为类istream的一个对象,而将cout视为类ostream的对象。

  13. C++的流类库预定义的4个流所联接起来的具体设备为:

    cin 与标准输入设备相联接

    cout 与标准输出设备相联接

    cerr 与标准错误输出设备相联接(非缓冲方式)

    clog 与标准错误输出设备相联接(缓冲方式)

  14. Bool(布尔型)在VC6.0中把输入的0识别为false,其他的值均识别为1。输出时,只有0和1两个值。如果默认输入输出格式不能满足自己的要求,就必须重载它们。

  15. ios_base类派生ios类,ios类又是istream类和ostream类的虚基类。

  16. 常量名及含义

常量名含义
skipws跳过输入中的空白
left输出数据按输出域左边对齐输出
right输出数据按输出域右边对齐输出
intermal在指定任何引导标志或基之后填充字符
dec转换基数为十进制形式
oct转换基数为八进制形式
hex转换基数为十六进制形式
showbase输出带有一个表示制式的字符
showpoint浮点输出时必须带有一个小数点和尾部的0
uppercase十六进制数值输出使用大写A~F,科学计数显示使用大写字母E
showpos在正数前添加一个“+”号
scientific使用科学计数法表示浮点数
fixed使用定点形式表示浮点数
untibuf每次插入之后,ostream::osfx刷新该流的缓冲区。默认缓冲单元为cerr
boolalpha把逻辑值输出为true和false(否则输出为1和0)
adjustfield对齐方式域(与left、right、internal配合使用,例如ios_base::adjustfield)
basefield数字方式域(与dex、oct、hex配合使用,例如ios_base::basefield)
floatfield浮点方式域(与fix、scientific配合使用,例如ios_base::floatfield)
  1. 处理标志的成员函数及其作用
成员函数作 用
long flags(long)允许程序员设置标志字的值,并返回以前所设置的标志字
long flags()仅返回当前的标志字
long setf(long,long)用于设置标志字的某一位,第2个参数指定所要操作的位,第1个参数指定为该参数所设置的值
long setf(long)用来设置参数指定的标志位
long unsetf(long)清除参数指定的标志位
int width(int)返回以前设置显示数据的域宽
int width()只返回当前域宽(默认宽度为0)
char fill(char)设置填充字符,设置的宽度小时,空余的位置用填充字符来填充,默认条件下是空格。这个函数返回以前设置的填充字符
char fill()获得当前的填充字符
int precision(int)返回以前设置的精度(小数点后的小数位数)
int precision返回当前设置的精度
  1. 直接使用格式控制:可以直接用在系统提供的输入输出流中,并且有些是成对的。加no前缀标识取消原操作。

  2. 用width(int)设置宽度的效果只对一次输入或输出有效,在完成一次输入或输出之后,宽度设置自动恢复为0(表示按实际数据宽度输入输出)。在设置输入时,实际输入的字符串最大长度为n-1(宽度n计入结束符)。setw(int)只对紧跟其后的输出有效。

  3. 在使用成员函数进行格式控制的时候,setf用来设置,unsetf用来恢复默认设置。

  4. 在C++里,文件操作是通过流来完成的。C++总共有输入文件流、输出文件流和输入输出文件流3种,并已将它们标准化。

  5. 要打开一个输入文件流,需要定义一个ifstream类型的对象;要打开一个输出文件流,需要定义一个ofstream类型的对象;如果要打开输入输出文件流,则要定义一个fstream类型的对象。这3种类型都定义在头文件<fstream>里。

  6. 对文件进行操作的方法如下:打开一个相应的文件流;把这个流和相应的文件关联起来。

    ofstream myStream;

    myStream.open(“myText.txt”);

    myStream.close();

  7. 如果指定文件路径,路径中的“\”号必须使用转义字符表示。

  8. 函数clear更多地是用于在已知流发生错误的情况下清除流的错误状态,也可以用于设置流的错误状态。除非发生致命错误(hardfail),否则可以使用函数clear清除流的错误状态。

  9. “!”运算符已经过了重载,它与fail函数执行相同的功能,因此表达式if(!cout)等价于if(cout.fail()),if(cout)等价于if(!cout.fail())。

  10. 成员函数及其功能

函 数功 能
bad()如果进行非法操作,返回true,否则返回false
clear()设置内部错误状态,如果用缺省参量调用则清除所有错误位
eof()如果提取操作已经到达文件尾,则返回true,否则返回false
good()如果没有错误条件和没有设置文件结束标志,返回true,否则返回false
fail()与good相反,操作失败返回false,否则返回true
is_open()判定流对象是否成功地与文件关联,若是,返回true,否则返回false

第10章 面向对象设计实例

  1. 抽象是面向对象方法中使用最为广泛的原则。

  2. 抽象的原则,主要是过程抽象和数据抽象。

  3. 寻找候选对象的基本方法的主要策略是从问题域、系统边界和系统责任三方面找出可能有的候选对象。

  4. 公有继承实际上是由两个不同部分组成的,即函数接口的继承和函数实现的继承。可概括成如下两点:

    (1)继承的总是成员函数的接口。对于基类是正确的任何事情,对于它的派生类必须也是正确的。

    (2)声明纯虚函数的目的是使派生类仅仅继承函数接口,而纯虚函数的实现则由派生类去完成。

    (3)声明虚函数的目的是使派生类既能继承基类对此虚函数的实现,又能继承虚函数提供的接口。

    (4)声明实函数的目的是使派生类既能继承基类对此实函数的实现,又能继承实函数提供的接口。

  5. 纯虚函数最显著的两个特征是:

    (1)它们必须由继承它的非抽象类重新说明

    (2)它们在抽象类中没有定义

  • 10
    点赞
  • 84
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杨倩-Yvonne

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值