C++要点总结

C++学习的几点总结:

num0:

源代码经编译器生成目标代码,经链接器将目标代码、启动代码以及库代码链接生成可执行代码;

main()函数由启动代码调用;

源代码开头最好注释指出源代码的文件名并简要地总结该程序(//exercise.cpp——the file is...);

虽然C++兼容了C的特性和函数,编写C++代码最好养成C++风格;

可能使用const int MONTHS=100代替预编译中#define MONTHS 100,const有更多优势;

C++的变量声明习惯是尽量在首次使用变量前声明;

C++中对于名称的度没有限制;

下划线和大写字母打头的变量名被保留给实现(编译器及其使用的资源)使用,所以编译不会报错,但会导致行为的不确定性;

climits库定义了比如:INT_MAX、SHRT_MAX等类型字符常量,sizeof(int)等价于sizeof number;

变量赋值可以使用十进制(42),也可以用进制(0x42、042),并且cout默认以十进制输出;

类型别名:第一种#define BYTE char、第二种、typedef char byte/typedef char *byte_poiniter;

for是次数循环、while是条件循环、do...while是出口条件循环,记住:do...while()后面有分号

if(age>17&&age<30)不等价于if(17<age<30),17<age<30会编译成(17<age)<30;


num1:——有关类的定义与声明
类体中声明后面一定要加分号;
类体中成员函数定义可以加或不加分号,编译不报错;
类体外成员函数定义可以加或不加分号,编译不报错;
类的定义一定要加分号,否则编译报错;
成员函数的声明中形参变量名可以不给出,只要形参的数据类型;

private:由该类中的函数和其友元函数访问,不能被任何其他访问,该类的对象也不能访问;

protected:可以被该类中的函数、子类的函数和其友元函数访问,但不能被该类的对象访问;

从类的用户角度来看,保护成员等价于私有成员,只是保护成员可以被派生类的成员函数引用;

public:可以被该类中的函数、子类的函数、其友元函数访问和该类的对象访问;


num2:

运行后的窗口闪现可以源代码后面添加:cout.get();/system("pause");

给字符变量赋值是用英文单引号:char a='r';

对于字符数组可以直接是使用cout<<arr<<endl输出各元素,而整形数组则要用for输出

cout<<arr会从地址为arr处输出字符,直到遇见'\0'时结束输出,而要输出arr的地址,则要写成cout<<(int *)arr

整形数组num[5]要用for循环输出数组元素,cout<<num;是输出数组的地址;

int arr[]作为函数参数,等价于int *arr,其实质是一个指针,但可以当做数组使用,如:arr[2];

使用普通参数,调用函数时是通过数据的拷贝来实现,保护了原始数据,而是用数组名将直接使用原始数据,存在原始数据被破坏的风险;

cout<<sizeof array;会显示出数组大小,而在调用函数int fill_fun(int arr[],int n)中使用cout<<sizeof arr;只会显示该指针占据的字节数,所以一定要传递给函数该数组大小;

int和char行可以进行计算;

C++新增一种变量初始化方式:int number(1002);

字符串后面默认添加"\0";


num3:——枚举变量

变量命名第一个必须是字母或下划线;

a=b=c=d=6;在c++中成立;

转移字符:'\n'【换行符】'\a'【振铃】'\"'【双引号,不作为字符串分隔符】;

枚举类型 enum spectrum {red,orange,yellow,green,blue,violet,indigo,ultraviolet};spectrum band=orange;

默认情况下第一个枚举变量的值为0,后面依次加1,也可以显示地改变枚举值:
enum spectrum {red,orange=12,yellow=13,green,blue=100,violet,indigo,ultraviolet};

并且后面没有被初始化的枚举变量值将比前面的值大1,因此violet=101;


num4:

输出流控制符,#include<iomanip>

dec                                         设置整数为十进制
oct                                         设置整数为八进制
hex                                         设置整数为十六进制
setbase(n)                               设置整数为n进制(n=8,10,16)
setfill(n)                                 设置字符填充,c可以是字符常或字符变量
setprecision(n)                        设置浮点数的效数字为
setw(n)                                   设置字段宽度为n位
setiosflags(ios::fixed)              设置浮点数以固定的小数位数显示
setiosflags(ios::scientific)        设置浮点数以科学计数法表示
setiosflags(ios::left)                输出左对齐
setiosflags(ios::right)               输出右对齐
setiosflags(ios::skipws)            忽略前导空格
setiosflags(ios::uppercase)       在以科学计数法输出E与十六进制输出X以大写输出,否则小写。
setiosflags(ios::showpos)          输出正数时显示"+"号
resetiosflags()                        终止已经设置的输出格式状态,在括号中应指定内容
endl                                       封装数据和行为,通知数据流输出一个回车并且刷新输出缓存区

如果在多个cout语句中使用相同的setw(n),并使用setiosflags(ios::right),可以实现各行数据右对齐,如果指定相同的精度,可以实现上下小数点对齐(cout<<setsflags(ios::fixed)<<setiosflags(ios::right)<<setprecision(2);)


num5:c=getchar();putchar('c');


num6:

如果函数的定义在函数调用之前,则应在函数定义中给出默认值。如果函数的定义在函数调用之后,则在函数调用之前需要有函数的声明,此时必须在函数声明中给出默认值,在函数定义时可以不给出默认值


num7:——staticextern和const关键

static关键字定义的作用有两个:

一是该局部变量赋值使用完过后,该变量值在内存中不释放,留到下一次使用;

二是程序设计中希望有些外部变量只限于被本文件引用,而不能被其他文件引用(或外部函数)

(在file1.cpp中定义一个变量int te=23,file2.cpp定义自己的static int te=2,file3.cpp需使用file1.cpp则extern int te,此时te值为23)

extern声明的表示在别的地方定义了变量或外部函数,只需在要使用的范围或文件内用extern声明;

定义只能由本文件使用的内部函数:static int function(int a,int b);

定义外部函数,可由其它文件调用:定义文件中int function(int a,int b),在需要使用的文件中extern int function(int a,int b)来声明;

const int Arsize=8;//作用类似于C中的define;

函数形参由于保护原始数据的需要,经常用到const形参;

由于数组名作为形参会直接使用原始数据,函数形参中用const int arr[]表示不能通过arr指针改变原始数据的值,并且const修饰指针就是不想通过该指针修改原始数据;

非const数据的地址可以赋给const指针或非const指针,但是const数据的地址只能赋给const指针;

const int var与int const var在修饰符号常量时,两种格式无多大区别,但当const修饰的是指针时就有区别,如果const位于星号的左侧(const int* pt/int const *pt),则const就是用来修饰指针所指向的变量,即指针指向为常量,如果const位于星号的右侧(int *const pt),const就是修饰指针本身,即指针本身是常量,只能使用一次取址运算符;



num8:

C++中有inline函数,带参数的宏定义更方便,所以在C++中基本不再用#define命令的宏定义;

传递数组信息的两种方式

1、数组名和长度function(arr,n)[int function(const int*arr,intlength)];

2、数组起始指针和数组结束指针function(cookie,cookie+Arsize)[int function(const int *begin,const int *end)]


num9:——数组初始化与输出

int数组赋值:a[]={1,2,3,4,5};a[3][3]={{1,2,3},{4,5,6},{7,8,9}}={1,2,3,4,5,6,7,8,9};

char数组char a[]={"Hello,everyone!"}="Hello,everyone!",自动添加"\0",遇到此标志就结束输出

字符指针:char *str="Hello,everyone!";

cout<<(int *)str<<endl;//可以输出字符指针的地址

sizeof(数组名)得到的是整个数组中的字节数;


num10:
c-风格字符串处理函数:<cstring>
strcat(char[] ,char[])  字符串连接函数
strcpy(char[] ,char[])  字符串复制函数
strcmp(char[] ,char[])  字符串比较函数(返回值,相等为0,大于为正,小于为负)
strlen(char[])          字符串长度函数

C++中string库包含了string类型和字符串数组;

string类具有自动调节大小的功能,并且赋值(=)、添加(+)、统计长度(str1.size())等操作简单;

无论是使用cin>>str,还是用赋值符号,string对象只能接受一个word,即遇空格停止读入;


num11:
指针使用前必须初始化,即设定地址,不然会报错;
不使用指针时通过return将处理结果值返回给程序主函数,而使用指针就不用return返回形参值了,可以直接并且调整多个值;
指针在循环过后,必须做越界判断和处理;

数组名代表数组第一个元素的地址,即int a[10];&a[0]=a;


num12:——各种指针定义
指向二维数组的指针:int (*p)[4];int a[3][4];*((p+i)+j)
函数指针:int(*p)(int,int);p=max;函数名即使函数的入口地址,必须将函数的入口地址赋给函数指针p;
返回指针值的函数:int *max(int,int);
指向指针的指针:char **p;

int &b=a;(C++中新增的引用);


num13:——结构体

结构体初始化:stud1={123,"Scotto",23,"男"};stud1.name="Scotto",成员运算符“.”;

结构体变量Student stud与结构体数组Student stud[20];

结构体指针Student *p=&stud1;

包括返回结构体的函数struct_my *function();

结构体指针:struct_my *pt;

p->name等价于(*p).name;


num14:——new与delete、静态联与动态联编

指针定义时一定要初始化一个确定、适当的地址,并且指针要作越界检查,这是关于使用指针的金科玉律;

变量是在编译时分配的、有名称的内存,指针真正用武之地在于在运行阶段分配未命名的内存以存储数值;

new动态分配内存,若分配失败,返回0,即空指针;(int *pt=new int;[int *ps=new int [5];])

delete释放指针指向的内存空间,不会删除指针本身,而且一定要用delete释放new生成的内存,否则发生内存泄露;(delete pt;[delete [] ps;])

不要使用delete来释放不是new分配的内存,比如释放声明变量所获得的内存;

不要使用delete释放同一内存块两次;

如果使用new[]为数组分配内存,则应使用delete []来释放;

对空指针应用delete是安全

动态数组元素的指定:int *ps=new int [3];ps[0]=34;*(ps+1)=32;

指针值加1后,其增加的值等于指向的类型占用字节数;

解除指针引用是指获得指针指向的值"*"为解除指针引用运算符

静态联编是通过声明来创建数组,编译时为其分配指定大小的内存空间;

动态联编使用new在程序运行时创建数组,大小可以在程序运行时指定;

访问new创建的动态结构体时,因为没有结构体变量名,可以使用ps->price或(*ps).price来访问结构成员

C++不保证新释放的内存就是下一次使用new时选择的内存,尽管使用的指针变量不变;


num15:

类是抽象的,不占内存,对象是具体的,占用存储空间,每个对象所占用的存储空间只是该对象的数据部分所占用的存储空间,同一类的成员函数共用一个存储空间;


num16:——class与struct定义的类
class与struct都可以定义类,只不过class定义时,不作声明默认为private,而struct默认为public;

接口与实现分离(声明与实现分离),开发商提供类库头文件的源代码和成员函数的目标代码(不提供源代码);


num17:——对象的构造函数与析构函数
构造函数是一种特殊的成员函数,与其他成员函数不同,不需要用户来调用它,而是在建立对象时自动执行;
构造函数没有返回值,所以不需要在定义构造函数时声明类型,这是与类所属的一般成员函数重要的不同之处;
无参数、有参数、参数初始化表;
带默认参数的参数初始化表:Box(int h=10,int w=12,int len=15):height(h),width(w),length(len){};
声明时指定默认参数值是方便而且高效的,它的作用相当于好几个重载的构造函数;

析构函数只有一个,不能重载;


num18:——对象、指针、常对象及常指针
对象数组初始化:Student stud[3]={Student(1001,18,87),Student(1002,19,79),Student(1003,18,76)};
对象指针:Time *pt;Time t;pt=&t;
指向对象公用数据成员的指针定义和指向普通变量的定义方法相同,int *p1;p1=&t.hour;()
指向对象公用成员函数的指针定义和指向普通函数的定义方法不同:

int (Time::*p2)(int h,int minute,int second);[数据类型名 (类名::*指针变量名)(参数表列)],p2=&Time::gettime;[指针变量名=&类名::成员函数名];

指向对象的常指针:Time *const pt;(指针值一次赋值后,不能再重新赋值)
指向常对象的指针:const Time *pt;(指向常变量的指针:const char *pt;);
常变量必须要用指向常变量的指针来指向,不能用一般的指针指向;


num19:——const成员函数与非const成员函数
非const成员函数可以引用本类中的所有数据成员,可以修改非const数据成员;
const成员函数可以引用本类中的数据成员,但不能修改非const数据成员;
如果一个对象被声明为常对象,则不能调用该对象的非const型成员函数(除了系统自动调用的隐式构造函数);
常对象只能保证其数据成员是const,如果在常对象中成员函数未加const声明,编译系统把它们作为非const成员函数;
常对象的构造函数只能用参数初始化表对常数据成员进行初始化,不能采用在构造函数中对常数据成员赋初值的方法;

常成员函数(void get_time()const;),声明和实现时都要有const关键字;


num20:



num21:——对象的赋值与复制
对象的赋值:Time t2;t2=t1;
对象的复制:Time t2(t1);(操作系统自动调用一个特殊的构造函数:复制构造函数[Box(Box &b){};])或Time t2=t1,t3=t2;

对象的赋值是对一个已经存在的对象赋值,因此必须先定义被赋值的对象,而对象的复制是新的对象不必实现定义存在;


num22:——静态数据成员static
静态数据成员static定义的数据成员:能够实现相同类下的变量共享,如果改变它的值,那么各个对象中该值都改变;
声明类而未定义对象,这时类的一般数据成员是不占内存空间的,只有在定义对象时,才为对象的数据成员分配空间;
静态的数据成员在内存中只占一份空间,只要在类中定义了静态数据成员,即使不定义对象,也为静态数据成员分配空间,它不随对象的建立而分配空间,也不随对象的撤销而释放;
静态数据成员可以初始化,但只能在类体外进行初始化int Box::height=10,初始化的时候不必加static;
静态数据成员既可以通过对象名引用,也可以通过类名来引用;
静态成员函数不属于某一对象,因此静态成员函数没有this指针;
静态成员函数的引用:Time::get_time()或time1.get_time();

静态成员函数主要是用来访问静态数据成员;


num23:
类的提前引用;
友元的关系是单向的;

友元的关系不能传递;


num24:——类模板
类模板
template <class numtype1,class numtype2>//无分号
class Compare
{
};
类体外成员函数定义:
template <class numtype1,class numtype2>
numtype1 Compare <class numtype1,class numtype2>::max()
{
}
定义类模板后对象的初始化:

compare <int,double>cmp(4,7);


num25:——运算符重载
运算符重载:函数类型 operator 运算符名称 (形参列表){对运算符的处理};
运算符被重载后,是运算符能够应用于类对象,其原有的功能仍然保留;
C++不允许用户定义新的运算符,只能对已有的C++运算符重载;

运算符重载可以作为类的成员函数,亦或者是友元函数

作为成员函数,可以通过this指针访问本类的数据成员,少写一个函数的参数,但必须要求运算符表达式第一个参数是类对象,重载函数作为友元函数时,运算符表达式前后的类型要和形参的类型保持一致,否则会出错;

运算符"++"、"--"重载,C++约定:在自增(自减)运算符重载函数中,增减一个int型形参,就是后置自增(自减)运算符

Time operator++()//前置自增运算符"++"重载函数

Time operator++(int)//后置自增运算符"++"重载函数


num26:——类型转化
隐式类型转化:int i;i=8.5+i;

显示类型转化:【来源于C语言】(int)89.5或【纯粹C++格式】int (89.5);

static_cast <typename> (thron)——四种强制类型转化操作符之一;

默认构造函数、初始化构造函数、复制对象构造函数、转换构造函数[标准数据转为类对象]

类型转换运算符函数operator double(){return real;}[类对象转为数据]


num27:——类的继承、派生
类的派生定义:
class StudentI:public Student
{
};
从基类接受全部成员函数和数据,只有派生类的构造函数和析构函数不能从基类继承;
private继承:基类的公用成员和保护成员在派生类中成了私有成员,其私有成员仍为基类似有;
protected继承:基类的公用成员和保护成员在派生类中成了保护成员,其私有成员仍为基类似有;
public继承:基类的公用成员和保护成员在派生类中保持原有访问属性,其私有成员仍为基类似有;
派生类的成员函数不能访问私有基类的私有成员,但可以访问私有基类的公有成员;
不管是私有基类还是公有基类,基类的私有成员是无法访问,基类的公有成员派生类可以访问,区别在于private继承基类的public数据及成员函数成为派生类的private数据和成员函数,public继承,基类的public数据成为派生类的public数据和成员函数;
希望在执行派生类的构造函数时,使派生类的数据成员和基类的数据成员同时都被初始化,可以在执行派生类的构造函数时,调用基类的构造函数;(例:student(n,nam,s):person(n,nam),title(s){};)
在类中对派生类构造函数声明时,不包括基类构造函数名及基类构造函数的函数列表,只有定义函数时才将它列出;
派生类对象构建时先调用基类构造函数,在调用派生类构造函数;

派生类对象释放时先执行派生类析构函数,再执行基类析构函数;


num28:——虚基类多重继承与指向基类的指针
多重继承引起数据成员或成员函数的二义性可以通过指定基类名来限定:c1.Student::display();
虚基类是针对多重继承,使得在继承间接共同基类时只保留一份成员;
可以用子类(派生类)对象对其基类对象指针赋值:A a1;B b1;a1=b1;(在赋值时舍弃派生类自己的成员);
可以用子类(派生类)对象对其基类对象引用进行赋值或初始化:A &r=b1;(等价于A &r=a1;);
利用基类指针或引用实现派生类对象的数据和成员函数调用可以编译通过,但不能访问派生类增加的成员;


num29:——类的组合、虚函数、纯虚函数和类的抽象

在一个类中将类的对象作为数据成员的,称为类的组合;

类的继承是纵向的,类的组合是横向的;
虚函数的作用是允许在派生类中重新定义与基类同名的函数,并且可以通过基类指针或引用来访问基类和派生类中的同名函数;

利用基类指针或引用+虚函数可以实现成员函数的动态多态性,而函数名相同相同,参数不同的会利用静态多态性即函数重载机制;

在基类中用virtual声明成员函数为虚函数,类体外定义虚函数时不需要再加virtual;

C++规定,当一个成员函数被声明为虚函数后,其派生类中的同名函数都自动成为虚函数;

如果用基类指针调用该成员函数,则系统会调用对象中基类部分的成员函数中未增加的数据部分

如果用派生类指针调用该成员函数,则系统会调用派生类对象中的成员函数所有数据成员,包括增加的数据成员部分

纯虚函数声明:virtual 函数类型 函数名(参数列表)=0,“=0”只起形式上的作用,告诉编译系统"这是纯虚函数";
纯虚函数的作用是在基类中为其派生类保留一个函数的名字,以便派生类根据需要对它进行定义;
抽象类:不用来定义对象而只作为一种基本类型用作继承的类,凡是包含纯虚函数的类都是抽象类;
通过基类指针或引用,加上虚函数,能通过派生类地址赋值给指向基类的指针,利用基类指针调用派生类成员函数可以显示派生类增加的数据成员,但是利用基类指针调用运算符重载,不能显示运算符中派生类增加的数据成员;
例:
Shape *pt;
Circle circle;
pt=&circle;

pt->display();//利用基类指针调用派生类成员函数可以显示派生类circle中增加的数据成员cout<<*pt<<endl;//但利用基类指针调用运算符重载"<<",不能显示运算符中派生类cirlce中"<<"增加的数据成员


num30:——iostream库中流对象成员函数
字符数组可以直接使用"cout<<数组名;"进行输出;
键盘输入用cin流,向显示器输出时用cout流,向显示器输出出错信息时用cerr和clog流;
cout可以将输出信息输出到显示器或磁盘文件,cerr只能输出到显示器,并且信息不经过缓冲区,clog和cerr类似,只不过输出信息
存放在缓冲区中,缓冲区满后或遇endl时向显示器输出,一般调试程序时使用cerr,cerr需要#include <iostream>
流成员函数所在库<iostream>
cout.setf(ios::hex);//设置以十六进制的输出状态
cout.unsetf(ios::hex);//终止以十六进制的输出状态
cout.width(n);//指定域宽
cout.fill('*');//设定空白填充
cout.setf(ios::scientific);//指定用科学记数法输出
cout.precision(n);//保留小数位

cout.put('c');//输出字符;==putchar('c')

cout.put(num),即使num为整型变量,也会输出其ASCII对应的字符;


链接:get()与getline()的面向行的输入

c=cin.get();//读取一个字符给c相当于getchar()

cin.get(ch);//读取一个字符给ch,成功则返回true值,失败返回false;
cin.get(字符数组或字符指针,字符个数[,终止字符]);//读取9个字符给ch字符数组,并且遇到终止字符将终止读入;
cin.getline(字符数组或字符指针,字符个数[,终止字符]);//作用于带参数的cin.get一样;

cin.eof()或cin.fail()返回值为true时,文件结束;//未遇到文件结束符

while(cin.get(ch))可以当做文件输入结束的判断,此语句效率很高,另外还有while(ch!=EOF)/while(cin)/while(!cin.eof())/while(!cin.fail());

如果cin位于测试条件中,则将被转换为bool型,输入成功为true,否则为false;

c=cin.peek();返回指针指向的下一个函数
cin.putback(ch);//将前面用get或getline函数从输入流中读取的字符ch返回到输入流,并插入到当前指针的位置;
cin.ignore(n,'A');//跳过输入流中n字符,或遇到指定的终止字符时提前结束;
putback()和ignore()都要放在cin.get前面才能起作用;

get和put不仅是标准I/O流的方法,也是文件流的方法,如
infile.get(ch)//从infile输入文件流中读取一个字符并赋值给字符ch,outfile.put(ch)//把字符ch的值输出到outfile文件输出流中;

string赋值时,遇空格则结束停止读入;

利用变址运算符[]可以输出string对象中单个的字符,string word;word[2]输出第三个字符;


对ASCII文件的读写用get和put函数,对二进制文件的读写用read和write函数
outfile.write(char  *buffer,int len);infile.read(char *buffer,int len);

C++中文件读位置的定位函数:infile.seekg(streamoff offset,seek_dir origin);
C++中文件写位置的定位函数:outfile.seekp(streamoff offset,seek_dir origin);
seek_dir表示移动的基准位置:ios::beg[文件开头]ios::cur[文件当前位置]ios::end[文件结尾]

字符串流:#include <iostrstream>

num31:——异常相应机制(try...catch)
try(检查异常)throw(抛出异常)catch(捕捉异常并处理)
throw抛出异常信息后,流程立即离开本函数,转到其上一级的函数
try-catch块中必须要使用“{}”将语句包括起来;

catch(...)捕捉任何异常信息

声明函数时定义函数可能出现的异常类型:
double function(double,double) throw(int,double);//可以抛出int和double类型异常;
double function(double,double) throw();//声明了一个不能抛出异常的函数;
double function(double,double);//该函数可以抛出任意类型的异常;

num32:——命名空间
命名空间:using namespace std;namesapce ns1;
如果有两个人写的库中有类同名或者函数同名,则主程序文件用include包含这两个库,编译或出错,必须在各自的库中使用不同的命名空间加以区别,主程序中使用重名函数或类时要用"::"指定命名空间;
namespace TV=television;
using ns1::student;
using namespace ns1;

由于C语言没有命名空间,头文件并不存放在命名空间,因此在C++程序文件中如果用到带有后缀.h的头文件时,不需必使用命名空间;


num33:——cctype

isalnum()如果参数是字母数字,即字母或数字,该函数返回true
isalpha()如果参数是字母,该函数返回真
isblank()如果参数是空格或水平制表符,该函数返回true
iscntrl()如果参数是控制字符,该函数返回true
isdigit()如果参数是数字(0~9),该函数返回true
isgraph()如果参数是除空格之外的打印字符,该函数返回true
islower()如果参数是小写字母,该函数返回true
isprint()如果参数是打印字符(包括空格),该函数返回true
ispunct()如果参数是标点符号,该函数返回true
isspace()

如果参数是标准空白字符,如空格、进纸、换行符、回车、水平制表符或者垂直制表符,该函数返回true

isupper()如果参数是大写字母,该函数返回true
isxdigit()如果参数是十六进制的数字,即0~9、a~f、A~F,该函数返回true
tolower()如果参数是大写字符,则返回其小写,否则返回该参数
toupper()如果参数是小写字母,则返回其大写,否则返回该参数

(2012-12-18)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值