C++学习笔记

1、在未出现函数调用时,形参并不占内存的存储单元,只有在函数开始调用时,形参才被分配内存单元。调用结束后,形参所占用的内存单元被释放。

2、实参对形参变量的传递是“值传递”,即单向传递。在内存中实参、形参分占不同的单元。

3、形参只作用于被调函数,可以在别的函数中使用相同的变量名。

4、在C++中,作用域共分为五类:块作用域、文件作用域、函数原型作用域、函数作用域和类的作用域。

  1)块作用域(局部变量)

我们把用花括号括起来的一部分程序称为一个块。在块内说明的标识符,只能在该块内引用,即其作用域在该块内,开始于标识符的说明处,结束于块的结尾处。 

  2)文件作用域(全局变量)

在函数外定义的变量称为全局变量。全局变量的作用域称为文件作用域,即在整个文件中都是可以访问的。 在块作用域内可通过作用域运算符“::”来引用与局部变量同名的全局变量。

  3)函数原型作用域

  4)函数作用域

  5)类的作用域

5、主函数main中定义的变量,也只在主函数中有效,同样属于局部变量。不同的函数可以使用相同名字的局部变量,它们在内存中分属不同的存储区间,互不干扰。变量名相同,局部更优先。

6、动态存储:在程序运行期间根据需要分配存储空间,函数结束后立即释放空间。若一个函数在程序中被调用两次,则每次分配的单元有可能不同。(动态局部变量)

     静态存储:在文件运行期间有固定的存储空间,直到文件运行结束。(静态局部变量和全局变量)auto、register、static

7、全局变量的两种形式

      静态(static)存储类别:它仅能在本文件中引用,即使在其它文件中用extern说明也不能使用。相当于限制了全局变量的作用域范围。

      extern  存储类别:全局变量的默认方式,当在一个文件中要引用另一个文件中的全局变量或在全局变量定义之前要引用它时,可用extern作说明,相当于扩大全局变量的作用域。


8、内联函数的实质是用存储空间(使用更多的存储空间)来换取时间(减少执行时间).内联函数的定义方法是,在函数定义时,在函数的类型前增加修饰词inline。 

9、带参数的宏与函数调用的区别

     相同:有实参、形参,代入调用。

     不同之处:1、函数调用先求表达式的值,然后代入形参,而宏只是机械替换。

                         2、函数调用时形参、实参进行类型定义,而宏不需要,只是作为字符串替代。       

                         3、函数调用是在运行程序时进行的,其目标代码短,但程序执行时间长。而宏调用是在编译之前完成的,运行时已将代码替换进程序中,目标代码长,执行时间稍快。    

10、

                                        

11、strlen 不包括'\0' sizeof是所占空间的大小                               

12、指针变量只能存放地址,不要将非地址数据赋给指针变量。指针变量作为函数参数与变量本身作函数参数不同,变量作函数参数传递的是具体值,而指针作函数参数传递的是内存的地址。

13、字符数组和字符指针变量都可以实现字符串的存储和运算,区别在于:字符数组名是常量,定义时必须指明占用的空间大小。字符指针变量是变量,里面存储的是字符型地址,可以整体赋值,但字符串必须以‘\0’结尾。

14、1、typedef可以定义类型,但不能定义变量。2、tyoedef只能对已经存在的类型名重新定义一个类型名,而不能创建一个新的类型名。

15、如果未加说明,类中成员默认的访问权限是private,即私有的。

16、在定义一个类时,要注意如下几点:
       1、类具有封装性,并且类只是定义了一种结构(样板),所以类中的任何成员数据均不能使用关键字extern,auto或register限定其存储类型。
       2、在定义类时,只是定义了一种导出的数据类型,并不为类分配存储空间,所以,在定义类中的数据成员时,不能对其初始化。如:
              class  Test {  int  x=5,y=6;   //是不允许的
              extern  float  x; //是不允许的  
              }

17、在C++语言中,结构体类型只是类的一个特例。结构体类型与类的唯一的区别在于:在类中,其成员的缺省的存取权限是私有的;而在结构体类型中,其成员的缺省的存取权限是公有的。

18、当我们定义一个类时,可以在类中直接定义函数体。这时成员函数在编译时是作为内联函数来实现的。 同时,我们也可以在类体外定义类的内联成员函数,在类体内说明函数,在类体外定义时,在成员函数的定义前面加上关键字inline。

19、在定义类时,只是定义了一种数据类型,即说明程序中可能会出现该类型的数据,并不为类分配存储空间。只有在定义了属于类的变量后,系统才会为类的变量分配空间。类的变量我们称之为对象。对象是类的实例,定义对象之前,一定要先说明该对象的类。在建立对象时,只为对象分配用于保存数据成员的内存空间,而成员函数的代码为该类的每一个对象所共享。 用成员选择运算符“.”只能访问对象的公有成员,而不能访问对象的私有成员或保护成员。若要访问对象的私有的数据成员,只能通过对象的公有成员函数来获取。 

20、同类型的对象之间可以整体赋值,这种赋值与对象的成员的访问权限无关。

21、线性表用来存放若干个整数,用一个指针指向其存放整数的首地址。当存放的数据大于原先开辟的空间时,线性表自动动态开辟空间,储存所有的整数。线性表有三个参数来描述:指向线性表存储空间首地址的指针变量List;无符号整数nMax,指示表的最大长度;无符号整数nElem,指示表中实际所放的数据个数。

21、线性表用来存放若干个整数,用一个指针指向其存放整数的首地址。当存放的数据大于原先开辟的空间时,线性表自动动态开辟空间,储存所有的整数。

22、构造函数是在创建对象时,使用给定的值来将对象初始化。析构函数的功能正好相反,是在系统释放对象前,对对象做一些善后工作。构造函数是类的成员函数,系统约定构造函数名必须与类名相同。构造函数提供了初始化对象的一种简单的方法。构造函数可以带参数、可以重载,同时没有返回值。

对构造函数,说明以下几点:
  1.构造函数的函数名必须与类名相同。构造函数的主要作用是完成初始化对象的数据成员以及其它的初始化工作

  2. 在定义构造函数时,不能指定函数返回值的类型,也不能指定为void类型。

  3. 一个类可以定义若干个构造函数。当定义多个构造函数时,必须满足函数重载的原则

  4.构造函数可以指定参数的缺省值。

  5.若定义的类要说明该类的对象时,构造函数必须是公有的成员函数。如果定义的类仅用于派生其它类时,则可将构造函数定义为保护的成员函数。

由于构造函数属于类的成员函数,它对私有数据成员、保护的数据成员和公有的数据成员均能进行初始化。

23、析构 函数的特点如下:
  1、析构函数是成员函数,函数体可写在类体内,也可写在类体外。

  2、析构函数是一个特殊的成员函数,函数名必须与类名相同,并在其前面加上字符“~”,以便和构造函数名相区别。

  3、析构函数不能带有任何参数,不能有返回值,不指定函数类型。

  4、一个类中,只能定义一个析构函数,析构函数不允许重载。

  5、析构函数是在撤消对象时由系统自动调用的。

在程序的执行过程中,当遇到某一对象的生存期结束时,系统自动调用析构函数,然后再收回为对象分配的存储空间。

24、在程序的执行过程中,对象如果用new运算符开辟了空间,则在类中应该定义一个析构函数,并在析构函数中使用delete删除由new分配的内存空间。因为在撤消对象时,系统自动收回为对象所分配的存储空间,而不能自动收回由new分配的动态存储空间。用new运算符为对象分配动态存储空间时,调用了构造函数,用delete删除这个空间时,调用了析构函数。当使用运算符delete删除一个由new动态产生的对象时,它首先调用该对象的析构函数,然后再释放这个对象占用的内存空间。用new运算符来动态生成对象数组时,自动调用构造函数,而用delete运算符来释放p1所指向的对象数组占用的存储空间时,在指针变量的前面必须加上[ ], 才能将数组元素所占用的空间全部释放。否则,只释放第0个元素所占用的空间。

25、在C++中所谓“继承”就是在一个已存在的类的基础上建立一个新的类。已存在的类称为“基类(base class)”或“父类(father class)”。新建立的类称为“派生类(derived class)”或“子类(son class)”。 protected 成员是一种具有血缘关系内外有别的成员。它对派生类的对象而言,是公开成员,可以访问,对血缘外部而言,与私有成员一样被隐蔽。

26、抽象类与保护的成员函数
当定义了一个类,这个类只能用作基类来派生出新的类,而不能用这种类来定义对象时,称这种类为抽象类。当对某些特殊的对象要进行很好地封装时,需要定义抽象类。将类的构造函数或析构函数的访问权限定义为保护的时,这种类为抽象类。将类的构造函数或析构函数的访问权限定义为保护的时,这种类为抽象类。 

27、构造函数不能被继承,派生类的构造函数必须调用基类的构造函数来初始化基类成员基类子对象。当派生类中新增加的数据或函数与基类中原有的同名时,若不加限制,则优先调用派生类中的成员。把一个类作为派生类的基类或把一个类的对象作为一个类的成员,在使用上是有区别的:在派生类中可直接使用基类的成员(访问权限允许的话),但要使用对象成员的成员时,必须在对象名后加上成员运算符“.”和成员名。

28、友元函数需要在类体内进行说明,在前面加上关键字friend。
一般格式为:
friend  <type> FuncName(<args>);

不管是按哪一种方式派生,基类的私有成员在派生类中都是不可见的。如果在一个派生类中要访问基类中的私有成员,可以将这个派生类声明为基类的友元。友元函数只能用对象名引用类中的数据。友元函数近似于普通的函数,它不带有this指针,因此必须将对象名或对象的引用作为友元函数的参数,这样才能访问到对象的成员。

29、私有派生
class  ClassName:   private BaseClassName
私有派生时,基类中公有成员和保护成员在派生类中均变为私有的,在派生类中仍可直接使用这些成员,基类中的私有成员,在派生类中不可直接使用。

基类:public: (变为私有)在派生类中使用,类外不可使用
    protected: (变为私有)在派生类中使用,类外不可使用
    private: 不能在派生类中和类外使用


30、

指针与引用的区别:

   1、指针是通过地址间接访问某个变量,而引用是通过别名直接访问某个变量。

    2、引用必须初始化,而一旦被初始化后不得再作为其它变量的别名。

&a的前面有类型符时(如int &a),它必然是对引用的声明;如果前面无类型符(如cout<<&a,则是取变量的地址。 

31、可以利用类作用域符::来指明数据或函数的来源。
如:A::x=a;
        c1.B::Show();

当派生类中新增加的数据或函数与基类中原有的同名时,若不加限制,则优先调用派生类中的成员。

32、把一个类作为派生类的基类或把一个类的对象作为一个类的成员,在使用上是有区别的:在派生类中可直接使用基类的成员(访问权限允许的话),但要使用对象成员的成员时,必须在对象名后加上成员运算符“.”和成员名。

33、在多重派生的过程中,若使公共基类在派生类中只有一个拷贝,则可将这种基类说明为虚基类。在派生类的定义中,只要在基类的类名前加上关键字virtual,就可以将基类说明为虚基类。用虚基类进行多重派生时,若虚基类没有缺省的构造函数,则在每一个派生类的构造函数中都必须有对虚基类构造函数的调用 (且首先调用)。


34、若要访问派生类中相同名字的函数,必须将基类中的同名函数定义为虚函数,这样,将不同的派生类对象的地址赋给基类的指针变量后,就可以动态地根据这种赋值语句调用不同类中的函数。

35、虚函数的定义和使用

      可以在程序运行时通过调用相同的函数名而实现不同功能的函数称为虚函数。定义格式为:
virtual  <type>  FuncName(<ArgList>);

一旦把基类的成员函数定义为虚函数,由基类所派生出来的所有派生类中,该函数均保持虚函数的特性。 在派生类中重新定义基类中的虚函数时,可以不用关键字virtual来修饰这个成员函数 。

36、关于虚函数,说明以下几点:
   1、当在基类中把成员函数定义为虚函数后,在其派生类中定义的虚函数必须与基类中的虚函数同名,参数的类型、顺序、参数的个数必须一一对应,函数的返回的类型也相同。若函数名相同,但参数的个数不同或者参数的类型不同时,则属于函数的重载,而不是虚函数。若函数名不同,显然这是不同的成员函数。

   2、实现这种动态的多态性时,必须使用基类类型的指针变量,并使该指针指向不同的派生类对象,并通过调用指针所指向的虚函数才能实现动态的多态性。

   3、虚函数必须是类的一个成员函数,不能是友元函数,也不能是静态的成员函数。

   4、在派生类中没有重新定义虚函数时,与一般的成员函数一样,当调用这种派生类对象的虚函数时,则调用其基类中的虚函数。

   5、可把析构函数定义为虚函数,但是,不能将构造函数定义为虚函数。

   6、虚函数与一般的成员函数相比较,调用时的执行速度要慢一些。为了实现多态性,在每一个派生类中均要保存相应虚函数的入口地址表,函数的调用机制也是间接实现的。因此,除了要编写一些通用的程序,并一定要使用虚函数才能完成其功能要求外,通常不必使用虚函数。

   7、一个函数如果被定义成虚函数,则不管经历多少次派生,仍将保持其虚特性,以实现“一个接口,多个形态”。

37、虚函数的访问
用基指针访问与用对象名访问用基指针访问虚函数时,指向其实际派生类对象重新定义的函数。实现动态聚束。通过一个对象名访问时,只能静态聚束。即由编译器在编译的时候决定调用哪个函数。

38、纯虚函数
在基类中不对虚函数给出有意义的实现,它只是在派生类中有具体的意义。这时基类中的虚函数只是一个入口,具体的目的地由不同的派生类中的对象决定。这个虚函数称为纯虚函数。

class    <基类名>
{ virtual <类型><函数名>(<参数表>)=0;
......
};

1、在定义纯虚函数时,不能定义虚函数的实现部分。
2、把函数名赋于0,本质上是将指向函数体的指针值赋为初值0。与定义空函数不一样,空函数的函数体为空,即调用该函数时,不执行任何动作。在没有重新定义这种纯虚函数之前,是不能调用这种函数的。

3、把至少包含一个纯虚函数的类,称为抽象类。这种类只能作为派生类的基类,不能用来说明这种类的对象。
其理由是明显的:因为虚函数没有实现部分,所以不能产生对象。但可以定义指向抽象类的指针,即指向这种基类的指针。当用这种基类指针指向其派生类的对象时,必须在派生类中重载纯虚函数,否则会产生程序的运行错误。

4、在以抽象类作为基类的派生类中必须有纯虚函数的实现部分,即必须有重载纯虚函数的函数体。否则,这样的派生类也是不能产生对象的。
综上所述,可把纯虚函数归结为:抽象类的唯一用途是为派生类提供基类,纯虚函数的作用是作为派生类中的成员函数的基础,并实现动态多态性。

39、由虚基类派生出的对象初始化时,直接调用虚基类的构造函数。因此,若将一个类定义为虚基类,则一定有正确的构造函数可供所有派生类调用。用虚基类进行多重派生时,若虚基类没有缺省的构造函数,则在每一个派生类的构造函数中都必须有对虚基类构造函数的调用 (且首先调用)。

40、当我们将类的某一个数据成员的存储类型指定为静态类型时,则由该类所产生的所有对象,其静态成员均共享一个存储空间,这个空间是在编译的时候分配的。换言之,在说明对象时,并不为静态类型的成员分配空间。

41、有关静态数据成员的使用,说明以下几点:
   1、类的静态数据成员是静态分配存储空间的,而其它成员是动态分配存储空间的(全局变量除外)。当类中没有定义静态数据成员时,在程序执行期间遇到说明类的对象时,才为对象的所有成员依次分配存储空间,这种存储空间的分配是动态的;而当类中定义了静态数据成员时,在编译时,就要为类的静态数据成员分配存储空间。

   2、必须在文件作用域中,对静态数据成员作一次且只能作一次定义性说明。因为静态数据成员在定义性说明时已分配了存储空间,所以通过静态数据成员名前加上类名和作用域运算符,可直接引用静态数据成员。在C++中,静态变量缺省的初值为0,所以静态数据成员总有唯一的初值。当然,在对静态数据成员作定义性的说明时,也可以指定一个初值。

   3、静态数据成员具有全局变量和局部变量的一些特性。静态数据成员与全局变量一样都是静态分配存储空间的,但全局变量在程序中的任何位置都可以访问它,而静态数据成员受到访问权限的约束。必须是public权限时,才可能在类外进行访问。

   4、为了保持静态数据成员取值的一致性,通常在构造函数中不给静态数据成员置初值,而是在对静态数据成员的定义性说明时指定初值。

42、对静态成员函数的用法说明以下几点:
   1、与静态数据成员一样,在类外的程序代码中,通过类名加上作用域操作符,可直接调用静态成员函数。 

   2、静态成员函数只能直接使用本类的静态数据成员或静态成员函数,但不能直接使用非静态的数据成员 (可以引用使用)。这是因为静态成员函数可被其它程序代码直接调用,所以,它不包含对象地址的this指针。 

   3、静态成员函数的实现部分在类定义之外定义时,其前面不能加修饰词static。这是由于关键字static不是数据类型的组成部分,因此,在类外定义静态成员函数的实现部分时,不能使用这个关键字
   4、不能把静态成员函数定义为虚函数。静态成员函数也是在编译时分配存储空间,所以在程序的执行过程中不能提供多态性。
   5、可将静态成员函数定义为内联的(inline),其定义方法与非静态成员函数完全相同。

43、const 、volatile对象和成员函数 

用const修饰的对象,只能访问该类中用const修饰的成员函数,而其它的成员函数是不能访问的。用volatile修饰的对象,只能访问该类中用volatile修饰的成员函数,不能访问其它的成员函数。当希望成员函数只能引用成员数据的值,而不允许成员函数修改数据成员的值时,可用关键词const修饰成员函数。一旦在用const修饰的成员函数中出现修改成员数据的值时,将导致编译错误。 

44、由于关键字const和volatile是属于数据类型的组成部分,因此,若在类定义之外定义const成员函数或volatile成员函数时,则必须用这二个关键字修饰,否则编译器认为是重载函数,而不是定义const成员函数或volatile成员函数。

用volatile修饰一个成员函数时,其一般格式为:
<type>  FuncName(<args>)   volatile;
其语义是指明成员函数具有一个易变的this指针,调用这个函数时,编译程序把属于此类的所有的数据成员都看作是易变的变量,编译器不要对这函数作优化工作。

45、指向类成员的指针
在C++中可以定义一种特殊的指针,它指向类中的成员函数或类中的数据成员。并可通过这样的指针来使用类中的数据成员或调用类中的成员函数。 

指向类中数据成员的指针变量,定义一个指向类中数据成员的指针变量的一般格式为:
<type>  ClassName:: *PointName;
其中type是指针PointName所指向数据的类型,它必须是类ClassName中某一数据成员的类型 

    1、指向类中数据成员的指针变量不是类中的成员,这种指针变量应在类外定义。
    2、与指向类中数据成员的指针变量同类型的任一数据成员,可将其地址赋给这种指针变量,赋值的一般格式为:
PointName = &ClassName::member;
这种赋值,是取该成员相对于该类的所在对象中的偏移量,即相对地址(距离开始位置的字节数)
如:mptr = &S::y;  
 表示将数据成员y的相对起始地址赋给指针变量mptr。
    3、用这种指针访问数据成员时,必须指明是使用那一个对象的数据成员。当与对象结合使用时,其用法为:
ObjectName.* PointName

   4、由于这种指针变量并不是类的成员,所以使用它只能访问对象的公有数据成员。若要访问对象的私有数据成员,必须通过成员函数来实现。

46、指向类中成员函数的指针变量
定义一个指向类中成员函数的指针变量的一般格式为:
<type>  (ClassName:: *PointName)(<ArgsList>);
其中PointName是指向类中成员函数的指针变量;ClassName是已定义的类名;type是通过函数指针PointName调用类中的成员函数时所返回值的数据类型,它必须与类ClassName中某一成员函数的返回值的类型相一致;<ArgsList>是函数的形式参数表。在使用这种指向成员函数的指针前,应先对其赋值
PointName= ClassName::FuncName;
同样地,只是将指定成员函数的相对地址赋给指向成员函数的指针。

对指向成员函数的指针变量的使用方法说明以下几点:
  1、指向类中成员函数的指针变量不是类中的成员,这种指针变量应在类外定义。
  2、不能将任一成员函数的地址赋给指向成员函数的指针变量,只有成员函数的参数个数、参数类型、参数的顺序和函数的类型均与这种指针变量相同时,才能将成员函数的指针赋给这种变量。 
  3、使用这种指针变量来调用成员函数时,必须指明调用那一个对象的成员函数,这种指针变量是不能单独使用的。用对象名引用。
  4、由于这种指针变量不是类的成员,所以用它只能调用公有的成员函数。若要访问类中的私有成员函数,必须通过类中的其它的公有成员函数。

  5、当一个成员函数的指针指向一个虚函数,且通过指向对象的基类指针或对象的引用来访问该成员函数指针时,同样地产生运行时的多态性。
  6、当用这种指针指向静态的成员函数时,可直接使用类名而不要列举对象名。这是由静态成员函数的特性所确定的。

47、运算符重载就是赋予已有的运算符多重含义。C++通过重新定义运算符,使它能够用于特定类的对象执行特定的功能。为了重载运算符,必须定义一个函数,并告诉编译器,遇到这个重载运算符就调用该函数,由这个函数来完成该运算符应该完成的操作。这种函数称为运算符重载函数,它通常是类的成员函数或者是友元函数。运算符的操作数通常也应该是类的对象。

                                    

当用成员函数实现运算符的重载时,运算符重载函数的参数只能有二种情况:没有参数或带有一个参数。对于只有一个操作数的运算符(如++),在重载这种运算符时,通常不能有参数;而对于有二个操作数的运算符,只能带有一个参数。这参数可以是对象,对象的引用,或其它类型的参数。在C++中不允许重载有三个操作数的运算符,只能对C++中已定义了的运算符进行重载,而且,当重载一个运算符时,该运算符的优先级和结合律是不能改变的。

                                        

用成员函数实现运算符的重载时,运算符的左操作数为当前对象,并且要用到隐含的this指针。运算符重载函数不能定义为静态的成员函数,因为静态的成员函数中没有this指针。

对双目运算符,重载为成员函数时,仅一个参数,另一个被隐含;重载为友元函数时,有两个参数,没有隐含参数。一般来说,单目运算符最好被重载为成员函数;对双目运算符最好被重载友元函数。

48、转换函数就是在类中定义一个成员函数,其作用是将类转换为某种数据类型。

    1. 转换函数必须是类的成员函数。

    2. 转换函数的调用是隐含的,没有参数。

注意,转换函数只能是成员函数,不能是友元函数。转换函数的操作数是对象。转换函数可以被派生类继承,也可以被说明为虚函数。

49、字符串类只定义了指针,并没有开辟具体的空间以存放字符串的内容,所以,无论是构造、析构还是加减等,均需要考虑动态开辟空间的问题。

50、文本文件的打开与关闭,在文件操作前,需要将程序与被操作的文件联系起来,使程序可以“引用”文件。在程序内定义一个文件类的对象,由该对象与文件发生联系,程序内所有的与文件的操作都是对该对象的操作。

51、infile.open(“myfile1.txt”);

打开文件“myfile1.txt”用于输入,并将这个文件与输入文件类对象infile建立联系,今后,在程序中,用到这个文件“myfile1.txt”的地方就用infile来代替。

         outfile.open(“myfile2.txt”);

打开文件“myfile2.txt”用于输出,并将这个文件与输出文件类对象outfile建立联系,今后,在程序中,用到这个文件“myfile2.txt”的地方就用outfile来代替。

52、从文件输入一字符或一行字符,当输入至文件尾时,函数返回值为0,可以据此来判断循环结束。

53、二进制文件的读写操作:若在文件的打开方式中没有特别说明,打开的文件均为ASCII码文件,若要打开二进制文件,则要特别说明并用特定的读写函数。

54、infile.eof( )    
当到达文件结束位置时,该函数返回一个非零值;否则返回零。

55、文件指针:当一打开文件,文件指针位于文件头,并随着读写字节数的多少顺序移动。

56、

                             

        学习总结:由于前面知识点跟C一样,所以理解起来容易一点,有些知识看起来就像复习和巩固一样,但是右面C里面没有的知识点理解起来就有些吃力,但是相信随着我对c++的学习,都会理解吸收的,加油!!!









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值