GCC-3.4.6源代码学习笔记(148 - 续)

 

继续前进之前,仔细阅读下面的注释。事实上,存在一个可能,我们会在下面失败退出。考虑以下例子:

void f (unsigned short i) {}

void f(unsigned char i) {}

int main () {

   f (5);

}

这两个函数实参的标准转换序列都不是彼此的子序列,因而需要下面的代码来进行进一步的调整。

 

compare_ics (continue)

 

5417    /* Otherwise, one sequence cannot be a subsequence of the other; they

5418      don't start with the same type. This can happen when comparing the

5419      second standard conversion sequence in two user-defined conversion

5420      sequences.  */

 

回忆在 build_conv 中,标准转换序列第一个节点的 ICS_STD_RANK 是该序列中出现的最低的转换等级(因为它以规范次序相反的次序排列节点)。因此标准转换序列的级别由其第一个转换节点的 ICS_STD_RANK 决定。

注意到在前端中,它故意在 STD_RANK USER_RANK 之间加入 PBOOL_RANK ,并且把它也视为一个 STD_CONV ,因此 ICS_STD_RANK 之间的比较可以处理“ 一个不是指针转换,或成员指针转换,或布尔转换的转换要优于这些转换。 ”这个情况。

 

compare_ics (continue)

 

5422    /* [over.ics.rank]

5423

5424      Or, if not that,

5425

5426      --the rank of S1 is better than the rank of S2 (by the rules

5427        defined below):

5428

5429      Standard conversion sequences are ordered by their ranks: an Exact

5430      Match is a better conversion than a Promotion, which is a better

5431      conversion than a Conversion.

5432

5433      Two conversion sequences with the same rank are indistinguishable

5434      unless one of the following rules applies:

5435

5436      --A conversion that is not a conversion of a pointer, or pointer

5437       to member, to bool is better than another conversion that is such

5438       a conversion. 

5439

5440      The ICS_STD_RANK automatically handles the pointer-to-bool rule,

5441      so that we do not have to check it explicitly.  */

5442    if (ICS_STD_RANK (ics1) < ICS_STD_RANK (ics2))

5443      return 1;

5444    else if (ICS_STD_RANK (ics2) < ICS_STD_RANK (ics1))

5445      return -1;

5446

5447    to_type1 = TREE_TYPE (ics1);

5448    to_type2 = TREE_TYPE (ics2);

5449

5450    if (TYPE_PTR_P (from_type1)

5451        && TYPE_PTR_P (from_type2)

5452        && TYPE_PTR_P (to_type1)

5453        && TYPE_PTR_P (to_type2))

5454    {

5455      deref_from_type1 = TREE_TYPE (from_type1);

5456      deref_from_type2 = TREE_TYPE (from_type2);

5457      deref_to_type1 = TREE_TYPE (to_type1);

5458      deref_to_type2 = TREE_TYPE (to_type2);

5459    }

5460    /* The rules for pointers to members A::* are just like the rules

5461      for pointers A*, except opposite: if B is derived from A then

5462      A ::* converts to B::*, not vice versa. For that reason, we

5463      switch the from_ and to_ variables here.  */

5464    else if ((TYPE_PTRMEM_P (from_type1) && TYPE_PTRMEM_P (from_type2)

5465             && TYPE_PTRMEM_P (to_type1) && TYPE_PTRMEM_P (to_type2))

5466           || (TYPE_PTRMEMFUNC_P (from_type1)

5467             && TYPE_PTRMEMFUNC_P (from_type2)

5468             && TYPE_PTRMEMFUNC_P (to_type1)

5469             && TYPE_PTRMEMFUNC_P (to_type2)))

5470    {

5471      deref_to_type1 = TYPE_PTRMEM_CLASS_TYPE (from_type1);

5472      deref_to_type2 = TYPE_PTRMEM_CLASS_TYPE (from_type2);

5473      deref_from_type1 = TYPE_PTRMEM_CLASS_TYPE (to_type1);

5474      deref_from_type2 = TYPE_PTRMEM_CLASS_TYPE (to_type2);

5475    }

5476

5477    if (deref_from_type1 != NULL_TREE

5478        && IS_AGGR_TYPE_CODE (TREE_CODE (deref_from_type1))

5479        && IS_AGGR_TYPE_CODE (TREE_CODE (deref_from_type2)))

5480    {

5481      /* This was one of the pointer or pointer-like conversions. 

5482

5483        [over.ics.rank]

5484   

5485        --If class B is derived directly or indirectly from class A,

5486         conversion of B* to A* is better than conversion of B* to

5487         void*, and conversion of A* to void* is better than

5488         conversion of B* to void*.  */

5489      if (TREE_CODE (deref_to_type1) == VOID_TYPE

5490         && TREE_CODE (deref_to_type2) == VOID_TYPE)

5491      {

5492        if (is_properly_derived_from (deref_from_type1,

5493                                 deref_from_type2))

5494          return -1;

5495        else if (is_properly_derived_from (deref_from_type2,

5496                                    deref_from_type1))

5497          return 1;

5498      }

5499      else if (TREE_CODE (deref_to_type1) == VOID_TYPE

5500             || TREE_CODE (deref_to_type2) == VOID_TYPE)

5501      {

5502        if (same_type_p (deref_from_type1, deref_from_type2))

5503        {

5504          if (TREE_CODE (deref_to_type2) == VOID_TYPE)

5505          {

5506            if (is_properly_derived_from (deref_from_type1,

5507                                      deref_to_type1))

5508              return 1;

5509          }

5510          /* We know that DEREF_TO_TYPE1 is `void' here.  */

5511          else if (is_properly_derived_from (deref_from_type1,

5512                                       deref_to_type2))

5513            return -1;

5514        }

5515      }

5516      else if (IS_AGGR_TYPE_CODE (TREE_CODE (deref_to_type1))

5517             && IS_AGGR_TYPE_CODE (TREE_CODE (deref_to_type2)))

5518       {

5519        /* [over.ics.rank]

5520

5521          --If class B is derived directly or indirectly from class A

5522           and class C is derived directly or indirectly from B,

5523        

5524          --conversion of C* to B* is better than conversion of C* to

5525            A *,

5526        

5527          --conversion of B* to A* is better than conversion of C* to

5528            A *  */

5529        if (same_type_p (deref_from_type1, deref_from_type2))

5530        {

5531          if (is_properly_derived_from (deref_to_type1,

5532                                   deref_to_type2))

5533            return 1;

5534          else if (is_properly_derived_from (deref_to_type2,

5535                                      deref_to_type1))

5536            return -1;

5537        }

5538        else if (same_type_p (deref_to_type1, deref_to_type2))

5539        {

5540          if (is_properly_derived_from (deref_from_type2,

5541                                   deref_from_type1))

5542            return 1;

5543          else if (is_properly_derived_from (deref_from_type1,

5544                                       deref_from_type2))

5545            return -1;

5546        }

5547      }

5548    }

 

注意 5464 行的 ELES IF 块。如果该代码交换‘源’及‘目的’类型(严格说是源类型永远指向派生类,目的类型指向基类类型),那么就可以就可以把下面的 4 种情况(【 3 】条文 13.3.3 .2 ):

C* B* 的转换优于 C* A* 的转换

B* A* 的转换优于 C* A* 的转换

B::* C::* 的转换优于 A::* C::* 的转换

A::* B::* 的转换优于 A::* C::* 的转换

合并为 2 个:

C* B* 的转换优于 C* A* 的转换

B* A* 的转换优于 C* A* 的转换

 

5216 bool

5217 is_properly_derived_from (tree derived, tree base)                                              in call.c

5218 {

5219    if (!IS_AGGR_TYPE_CODE (TREE_CODE (derived))

5220        || !IS_AGGR_TYPE_CODE (TREE_CODE (base)))

5221      return false;

5222

5223    /* We only allow proper derivation here. The DERIVED_FROM_P macro

5224      considers every class derived from itself.  */

5225    return (!same_type_ignoring_top_level_qualifiers_p (derived, base)

5226           && DERIVED_FROM_P (base, derived));

5227 }

 

注意到如果 derived base 的类型相同, is_properly_derived_from 将返回 false ,因为 DERIVED_FROM_P 使用 lookup_base 来进行查找,它仅搜索 derived 的基类。而下面的 non_reference 访问 REFERENCE_TYPE 中的 TREE_TYPE ,而不管其它节点。

 

compare_ics (continue)

 

5549    else if (CLASS_TYPE_P (non_reference (from_type1))

5550          && same_type_p (from_type1, from_type2))

5551    {

5552      tree from = non_reference (from_type1);

5553

5554      /* [over.ics.rank]

5555  

5556        --binding of an expression of type C to a reference of type

5557         B& is better than binding an expression of type C to a

5558         reference of type A&

5559

5560        --conversion of C to B is better than conversion of C to A,  */

5561      if (is_properly_derived_from (from, to_type1)

5562          && is_properly_derived_from (from, to_type2))

5563      {

5564        if (is_properly_derived_from (to_type1, to_type2))

5565          return 1;

5566        else if (is_properly_derived_from (to_type2, to_type1))

5567          return -1;

5568      }

5569    }

5570    else if (CLASS_TYPE_P (non_reference (to_type1))

5571           && same_type_p (to_type1, to_type2))

5572    {

5573      tree to = non_reference (to_type1);

5574

5575      /* [over.ics.rank]

5576

5577        --binding of an expression of type B to a reference of type

5578         A & is better than binding an expression of type C to a

5579         reference of type A&,

5580

5581        --conversion of B to A is better than conversion of C to A  */

5582      if (is_properly_derived_from (from_type1, to)

5583         && is_properly_derived_from (from_type2, to))

5584      {

5585        if (is_properly_derived_from (from_type2, from_type1))

5586          return 1;

5587        else if (is_properly_derived_from (from_type1, from_type2))

5588          return -1;

5589      }

5590    }

5591

5592    /* [over.ics.rank]

5593

5594       --S1 and S2 differ only in their qualification conversion and yield

5595         similar types T1 and T2 (_conv.qual_), respectively, and the cv-

5596        qualification signature of type T1 is a proper subset of the cv-

5597        qualification signature of type T2  */

5598    if (TREE_CODE (ics1) == QUAL_CONV

5599        && TREE_CODE (ics2) == QUAL_CONV

5600        && same_type_p (from_type1, from_type2))

5601      return comp_cv_qual_signature (to_type1, to_type2);

5602

5603    /* [over.ics.rank]

5604      

5605       --S1 and S2 are reference bindings (_dcl.init.ref_), and the

5606        types to which the references refer are the same type except for

5607       top-level cv-qualifiers, and the type to which the reference

5608       initialized by S2 refers is more cv-qualified than the type to

5609       which the reference initialized by S1 refers */

5610       

5611    if (target_type1 && target_type2

5612        && same_type_ignoring_top_level_qualifiers_p (to_type1, to_type2))

5613      return comp_cv_qualification (target_type2, target_type1);

5614

5615    /* Neither conversion sequence is better than the other.  */

5616    return 0;

5617 }

 

joust 5704 行, compare_ics 把结果返回给 comp ,如果结果不是 0 ,表示我们已经知道谁是更好的。那么在 5708 行, warn_sign_promo 如果不是 0 ,表示对选择从无符号到有符号的提升优先于到同样大小无符号类型的转换的重载解析给出警告。

另外注意到在这里 compare_ics 为每一对参数所调用,因此每一次的优胜者必须是相同的;否则就需要扩展规则来进行判断。而进入到下面的代码,并且 winner 不为 0 ,表示优胜者已经找到了。

 

joust (continue)

 

5749    /* warn about confusing overload resolution for user-defined conversions,

5750      either between a constructor and a conversion op, or between two

5751      conversion ops.  */

5752    if (winner && warn_conversion && cand1->second_conv

5753       && (!DECL_CONSTRUCTOR_P (cand1->fn) || !DECL_CONSTRUCTOR_P (cand2->fn))

5754       && winner != compare_ics (cand1->second_conv, cand2->second_conv))

5755    {

5756      struct z_candidate *w, *l;

5757      bool give_warning = false;

5758       

5759      if (winner == 1)

5760        w = cand1, l = cand2;

5761      else

5762        w = cand2, l = cand1;

5763       

5764      /* We don't want to complain about `X::operator T1 ()'

5765        beating `X::operator T2 () const', when T2 is a no less

5766        cv-qualified version of T1.  */

5767      if (DECL_CONTEXT (w->fn) == DECL_CONTEXT (l->fn)

5768         && !DECL_CONSTRUCTOR_P (w->fn) && !DECL_CONSTRUCTOR_P (l->fn))

5769      {

5770        tree t = TREE_TYPE (TREE_TYPE (l->fn));

5771        tree f = TREE_TYPE (TREE_TYPE (w->fn));

5772     

5773        if (TREE_CODE (t) == TREE_CODE (f) && POINTER_TYPE_P (t))

5774        {

5775          t = TREE_TYPE (t);

5776          f = TREE_TYPE (f);

5777        }

5778         if (!comp_ptr_ttypes (t, f))

5779          give_warning = true;

5780      }

5781      else

5782        give_warning = true;

5783       

5784      if (!give_warning)

5785        /*NOP*/ ;

5786      else if (warn)

5787      {

5788        tree source = source_type (TREE_VEC_ELT (w->convs, 0));

5789        if (! DECL_CONSTRUCTOR_P (w->fn))

5790          source = TREE_TYPE (source);

5791        warning ("choosing `%D' over `%D'", w->fn, l->fn);

5792        warning ("  for conversion from `%T' to `%T'",

5793                 source, TREE_TYPE (w->second_conv));

5794        warning ("  because conversion sequence for the argument is better");

5795      }

5796      else

5797        add_warning (w, l);

5798    }

5799

5800    if (winner)

5801      return winner;

 

上面的 warn_conversion 如果不是 0 ,如果执行了一个可能具有令人困惑的结果的类型转换,给出警告。如果满足 5754 行条件, compare_ics 发现参数转换上优胜的候选者,在返回值类型的转换上败下阵来;不过,这个发现并不会改变选择的结果。

如果这两个候选者被发现其参数的转换上不可区分,在这里 winner 0 ,那么往下继续。首先,非模板总是优于模板的;而特化程度高的模板优于特化程度低的模板。除此之外,返回值类型的转换也能选出优胜者。

 

joust (continue)

 

5803    /* or, if not that,

5804      F 1 is a non-template function and F2 is a template function

5805      specialization.  */

5806          

5807    if (! cand1->template && cand2->template)

5808      return 1;

5809    else if (cand1->template && ! cand2->template)

5810      return -1;

5811   

5812    /* or, if not that,

5813      F 1 and F2 are template functions and the function template for F1 is

5814      more specialized than the template for F2 according to the partial

5815      ordering rules.  */

5816   

5817    if (cand1->template && cand2->template)

5818    {

5819      winner = more_specialized

5820           (TI_TEMPLATE (cand1->template), TI_TEMPLATE (cand2->template),

5821            DEDUCE_ORDER,

5822            /* Tell the deduction code how many real function arguments

5823              we saw, not counting the implicit 'this' argument. But,

5824              add_function_candidate() suppresses the "this" argument

5825              for constructors.

5826

5827              [temp.func.order]: The presence of unused ellipsis and default

5828               arguments has no effect on the partial ordering of function

5829              templates.  */

5830            TREE_VEC_LENGTH (cand1->convs)

5831               - (DECL_NONSTATIC_MEMBER_FUNCTION_P (cand1->fn)

5832               - DECL_CONSTRUCTOR_P (cand1->fn)));

5833      if (winner)

5834        return winner;

5835    }

5836

5837    /* or, if not that,

5838      the context is an initialization by user-defined conversion (see

5839      _dcl.init_ and _over.match.user_) and the standard  conversion

5840      sequence from the return type of F1 to the destination type (i.e.,

5841      the type of the entity being initialized) is a better conversion

5842      sequence than the standard conversion sequence from the return type

5843      of F2 to the destination type.  */

5844

5845    if (cand1->second_conv)

5846    {

5847      winner = compare_ics (cand1->second_conv, cand2->second_conv);

5848      if (winner)

5849        return winner;

5850    }

 

如果在上面仍然没有结果,【 3 】条文 13.3.1 .2 “表达式中的操作符”,条款 3 ,显示内建操作符也是候选者,当:

对于操作符‘ , ’,一元操作符‘ & ’,或操作符‘ -> ’,内建候选者集是空的。对于其他操作符,内建候选者包括所有在 13.6 定义的候选操作符函数,它们与给定的操作符比较,

具有相同的操作符名字,及

接受相同数目的操作数,及

接受的类型,给定的操作数根据 13.3.3 .1 可以转换到,及

与任一非模板、非成员的候选者的参数类型列表不相同。

看到最后一个条件,如果内建操作符具有与任一非模板、非成员的候选者相同的参数类型列表,它将被丢弃。记得在前端中,内建对象是节点 IDENTIFIER_NODE

 

joust (continue)

 

5852 Check whether we can discard a builtin candidate, either because we

5853      have two identical ones or matching builtin and non-builtin candidates.

5854

5855      (Pedantically in the latter case the builtin which matched the user

5856      function should not be added to the overload set, but we spot it here.

5857      

5858      [over.match.oper]

5859      ... the builtin candidates include ...

5860      - do not have the same parameter type list as any non-template

5861        non-member candidate.  */

5862                             

5863    if (TREE_CODE (cand1->fn) == IDENTIFIER_NODE

5864        || TREE_CODE (cand2->fn) == IDENTIFIER_NODE)

5865    {

5866      for (i = 0; i < len; ++i)

5867        if (!same_type_p (TREE_TYPE (TREE_VEC_ELT (cand1->convs, i)),

5868                       TREE_TYPE (TREE_VEC_ELT (cand2->convs, i))))

5869          break ;

5870      if (i == TREE_VEC_LENGTH (cand1->convs))

5871      {

5872        if (cand1->fn == cand2->fn)

5873          /* Two built-in candidates; arbitrarily pick one.  */

5874          return 1;

5875        else if (TREE_CODE (cand1->fn) == IDENTIFIER_NODE)

5876          /* cand1 is built-in; prefer cand2.  */

5877          return -1;

5878        else

5879          /* cand2 is built-in; prefer cand1.  */

5880          return 1;

5881      }

5882    }

5883

5884    /* If the two functions are the same (this can happen with declarations

5885      in multiple scopes and arg-dependent lookup), arbitrarily choose one.  */

5886    if (DECL_P (cand1->fn) && DECL_P (cand2->fn)

5887        && equal_functions (cand1->fn, cand2->fn))

5888      return 1;

 

我们来到这里,要么因为参数的转换不能给出一致的答案,要么还不能看出谁是更优。对于后者,无疑是一个二义性的情形。而对于前者,两个候选各有优劣,那么我们换个思路,现在我们仅比较两者中最差的转换。没那么差的获胜。如果都一样差,那没办法,这是如假包换的二义性!

 

joust (continue)

 

5890 tweak:

5891

5892    /* Extension: If the worst conversion for one candidate is worse than the

5893      worst conversion for the other, take the first.  */

5894    if (!pedantic )

5895    {

5896      int rank1 = IDENTITY_RANK, rank2 = IDENTITY_RANK;

5897      struct z_candidate *w = 0, *l = 0;

5898

5899      for (i = 0; i < len; ++i)

5900      {

5901        if (ICS_RANK (TREE_VEC_ELT (cand1->convs, i+off1)) > rank1)

5902          rank1 = ICS_RANK (TREE_VEC_ELT (cand1->convs, i+off1));

5903        if (ICS_RANK (TREE_VEC_ELT (cand2->convs, i+off2)) > rank2)

5904          rank2 = ICS_RANK (TREE_VEC_ELT (cand2->convs, i+off2));

5905      }

5906      if (rank1 < rank2)

5907        winner = 1, w = cand1, l = cand2;

5908      if (rank1 > rank2)

5909        winner = -1, w = cand2, l = cand1;

5910      if (winner)

5911      {

5912        if (warn)

5913        {

5914          pedwarn ("/

5915 ISO C++ says that these are ambiguous, even /

5916 though the worst conversion for the first is better than /

5917 the worst conversion for the second:");

5918                   print_z_candidate (_("candidate 1:"), w);

5919                   print_z_candidate (_("candidate 2:"), l);

5920        }

5921        else

5922          add_warning (w, l);

5923        return winner;

5924      }

5925    }

5926

5927    my_friendly_assert (!winner, 20010121);

5928    return 0;

5929 }

 

joust 退出,而我们已经看了完整的 tourney ,只要找到最优的候选者,它就返回非 NULL 值。否则, build_user_type_conversion_1 2501 行返回一个 AMBIG_CONV

 

build_user_type_conversion_1 (continue)

 

2483     if (cand == 0)

2484    {

2485      if (flags & LOOKUP_COMPLAIN)

2486      {

2487        error ("conversion from `%T' to `%T' is ambiguous",

2488             fromtype, totype);

2489        print_z_candidates (candidates);

2490      }

2491

2492      cand = candidates;       /* any one will do */

2493      cand->second_conv = build1 (AMBIG_CONV, totype, expr);

2494      ICS_USER_FLAG (cand->second_conv) = 1;

2495      if (!any_strictly_viable (candidates))

2496        ICS_BAD_FLAG (cand->second_conv) = 1;

2497      /* If there are viable candidates, don't set ICS_BAD_FLAG; an

2498        ambiguous conversion is no worse than another user-defined

2499        conversion.  */

2500

2501      return cand;

2502    }

2503

2504    /* Build the user conversion sequence.  */

2505    convs = build_conv

2506                 (USER_CONV,

2507                  (DECL_CONSTRUCTOR_P (cand->fn)

2508                    ? totype : non_reference (TREE_TYPE (TREE_TYPE (cand->fn)))),

2509                      build1 (IDENTITY_CONV, TREE_TYPE (expr), expr));

2510    TREE_OPERAND (convs, 1) = build_zc_wrapper (cand);

2511

2512    /* Combine it with the second conversion sequence.  */

2513    cand->second_conv = merge_conversion_sequences (convs,

2514                                               cand->second_conv);

2515

2516    if (cand->viable == -1)

2517      ICS_BAD_FLAG (cand->second_conv) = 1;

2518

2519    return cand;

2520 }

 

看到上面在 2510 行, build_zc_wrapper 把找到的最优候选者构建为 convs 的第一个操作数。

 

1645 tree

1646 build_zc_wrapper (struct z_candidate * ptr)                                                        in tree.c

1647 {

1648    tree t = make_node (WRAPPER);

1649    WRAPPER_ZC (t) = ptr;

1650    return t;

1651 }

 

相关的数据结构定义如下。在这里,我们可以清楚地看到 convs 的第一个操作数记录了实现指定转换的最优转换函数。

 

434    #define WRAPPER_ZC (NODE) (((struct tree_wrapper*)WRAPPER_CHECK (NODE))->z_c)

435   

436    struct tree_wrapper GTY(())                                                                     in cp-tree.h

437    {

438      struct tree_common common;

439      struct z_candidate *z_c;

440    };

 

那么下面的函数把 user_seq 添加到 std_seq 的末尾。其中 std_seq 是应用于返回值的转换序列,而 user_seq 是以一个 USER_CONV 开头的用户定义转换序列。不要为 std_seq 是名字所迷惑,它也可能是一个用户定义转换序列。

 

2326 static tree

2327 merge_conversion_sequences (tree user_seq, tree std_seq)                                  in call.c

2328 {

2329    tree *t;

2330

2331    my_friendly_assert (TREE_CODE (user_seq) == USER_CONV,

2332              20030306);

2333

2334     /* Find the end of the second conversion sequence.  */

2335    t = &(std_seq);

2336    while (TREE_CODE (*t) != IDENTITY_CONV)

2337      t = &TREE_OPERAND (*t, 0);

2338

2339    /* Replace the identity conversion with the user conversion

2340      sequence.  */

2341    *t = user_seq;

2342

2343    /* The entire sequence is a user-conversion sequence.  */

2344    ICS_USER_FLAG (std_seq) = 1;

2345

2346    return std_seq;

2347 }

 

cand 被返回到 implicit_conversion ,这个函数把上面所准备的 cand second_conv 域返回作为隐式转换序列(首先是返回值的序列,然后是参数的序列)。

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值