c++c++使用类(运算符重载)

运算符重载基础

1)返回自定义数据类型的引用可以让多个运算符表达式串联起来。(不要返回局部变量的引用)
2)重载函数参数列表中的顺序决定了操作数的位置。
3)重载函数的参数列表中至少有一个是用户自定义的类型,防止程序员为内置数据类型重载运算符。
4)如果运算符重载既可以是成员函数也可以是全局函数,应该优先考虑成员函数,这样更符合运算符重载的初衷。
5)重载函数不能违背运算符原来的含义和优先级。
6)不能创建新的运算符。

重载加减运算符

#include <iostream>         // 包含头文件。
using namespace std;        // 指定缺省的命名空间。

class CGirl       // 超女类CGirl。
{
    friend CGirl &operator+(CGirl& g, int score);
    friend CGirl& operator+(int score, CGirl& g);
    friend CGirl& operator+(CGirl& g1, CGirl& g2);
    //重载减号
    friend CGirl &operator-(CGirl& g, int score);
    friend CGirl& operator-(int score, CGirl& g);
    friend CGirl& operator-(CGirl& g1, CGirl& g2);
private:
    int         m_xw;        // 胸围。
    int         m_score;    // 分数。
public:
    string    m_name;   // 姓名。

    // 默认构造函数。
    CGirl() { m_name = "西施";  m_xw = 87;  m_score = 30; }
    // 自我介绍的方法。
    void show() { cout << "姓名:" << m_name << ",胸围:" << m_xw << ",评分:" << m_score << endl; }

    //CGirl& operator-(int score)    // 给超女减分的函数。
    //{
    //    m_score = m_score - score;
    //    return *this;
    //}
};

//重载加号运算符
CGirl& operator+(CGirl& g, int score)    // 给超女加分的函数。
{
    g.m_score = g.m_score + score;
    return g;
}
CGirl& operator+(int score,CGirl& g)    // 给超女加分的函数。
{
    g.m_score = g.m_score + score;
    return g;
}
CGirl& operator+(CGirl& g1, CGirl& g2)    // 给超女加分的函数。
{
    g1.m_score = g1.m_score + g2.m_score;
    return g1;
}

//重载减号运算符
CGirl& operator-(CGirl& g, int score)    // 给超女加分的函数。
{
    g.m_score = g.m_score - score;
    return g;
}
CGirl& operator-(int score,CGirl& g)    // 给超女加分的函数。
{
    g.m_score = g.m_score - score;
    return g;
}
CGirl& operator-(CGirl& g1, CGirl& g2)    // 给超女加分的函数。
{
    g1.m_score = g1.m_score - g2.m_score;
    return g1;
}

int main()
{
    // 导演的要求:每轮表演之后,给超女加上她的得分。
    CGirl g;

    cout<<"重载加号运算符"<<endl;
    operator+(g,30);
    g.show();
    g+30;
    g.show();
    
    g =  g+g;
    g.show();
    cout<<"重载减号运算符"<<endl;
    operator-(g,30);
    g.show();
    g-30;
    g.show();
    
    g =  g-g;
    g.show();
}

运算符重载函数的返回值类型要与运算符本身的含义一致。
成员函数版本的重载运算符函数:形参个数比运算符的操作数个数少一个,其中的一个操作数隐式传递了调用对象。
如果同时重载了非成员函数和成员函数版本,会出现二义性。

#include <iostream>         // 包含头文件。
using namespace std;        // 指定缺省的命名空间。

class CGirl       // 超女类CGirl。
{
    // friend CGirl &operator+(CGirl& g, int score);
    // friend CGirl& operator+(int score, CGirl& g);
    // friend CGirl& operator+(CGirl& g1, CGirl& g2);
    // //重载减号
    // friend CGirl &operator-(CGirl& g, int score);
    // friend CGirl& operator-(int score, CGirl& g);
    // friend CGirl& operator-(CGirl& g1, CGirl& g2);
private:
    int         m_xw;        // 胸围。
    int         m_score;    // 分数。
public:
    string    m_name;   // 姓名。

    // 默认构造函数。
    CGirl() { m_name = "西施";  m_xw = 87;  m_score = 30; }
    // 自我介绍的方法。
    void show() { cout << "姓名:" << m_name << ",胸围:" << m_xw << ",评分:" << m_score << endl; }

    //成员函数的重载
    CGirl& operator-(int score)    // 给超女减分的函数。
    {
       m_score = m_score - score;
       return *this;
    }
};

// //非成员函数的重载    重载加号运算符
// CGirl& operator+(CGirl& g, int score)    // 给超女加分的函数。
// {
//     g.m_score = g.m_score + score;
//     return g;
// }
// CGirl& operator+(int score,CGirl& g)    // 给超女加分的函数。
// {
//     g.m_score = g.m_score + score;
//     return g;
// }
// CGirl& operator+(CGirl& g1, CGirl& g2)    // 给超女加分的函数。
// {
//     g1.m_score = g1.m_score + g2.m_score;
//     return g1;
// }

// //重载减号运算符
// CGirl& operator-(CGirl& g, int score)    // 给超女加分的函数。
// {
//     g.m_score = g.m_score - score;
//     return g;
// }
// CGirl& operator-(int score,CGirl& g)    // 给超女加分的函数。
// {
//     g.m_score = g.m_score - score;
//     return g;
// }
// CGirl& operator-(CGirl& g1, CGirl& g2)    // 给超女加分的函数。
// {
//     g1.m_score = g1.m_score - g2.m_score;
//     return g1;
// }

int main()
{
    // 导演的要求:每轮表演之后,给超女加上她的得分。
    CGirl g;

    // cout<<"重载加号运算符"<<endl;
    // operator+(g,30);
    // g.show();
    // g+30;
    // g.show();
    
    // g =  g+g;
    // g.show();
    cout<<"重载减号运算符"<<endl;
    // operator-(g,30);
    // g.show();
    g-30-5;
    g.show();
    
    // g =  g-g;
    // g.show();
}

以下运算符只能通过成员函数进行重载:

  • = 赋值运算符
  • () 函数调用运算符
  • [] 下标运算符
  • -> 通过指针访问类成员的运算符

重载关系运算符

#include <iostream>         // 包含头文件。
using namespace std;        // 指定缺省的命名空间。

class CGirl       // 超女类CGirl。
{
    string    m_name;     // 姓名。
    int         m_yz;           // 颜值:1-千年美人;2-百年美人;3-绝代美人;4-极漂亮;5-漂亮;6-一般;7-歪瓜裂枣。
    int         m_sc;           // 身材:1-火辣;2-...;3-...;4-...;5-...;6-...;7-膘肥体壮。
    int         m_acting;    // 演技:1-完美;2-...;3-...;4-...;5-...;6-...;7-四不像。
public:
    // 四个参数的构造函数。
    CGirl(string name, int yz, int sc, int acting) { m_name = name;  m_yz = yz;  m_sc = sc; m_acting = acting; }
    // 比较两个超女的商业价值。
    bool operator==(const CGirl& g1)      // 相等==
    {
        if ((m_yz + m_sc + m_acting) == (g1.m_yz + g1.m_sc + g1.m_acting)) return true;
        return false;
    }
    bool operator>(const CGirl& g1)      // 大于>
    {
        if ((m_yz + m_sc + m_acting) < (g1.m_yz + g1.m_sc + g1.m_acting)) return true;
        return false;
    }
    bool operator<(const CGirl& g1)      // 小于<
    {
        if ((m_yz + m_sc + m_acting) > (g1.m_yz + g1.m_sc + g1.m_acting)) return true;
        return false;
    }
};

int main()
{
    CGirl  g1("西施", 1, 2, 12), g2("冰冰", 1, 2, 2);
      
    if (g1==g2)
        cout << "西施和冰冰的商业价值相同。\n";
    else
        if (g1>g2)
            cout << "西施商业价值相同比冰冰大。\n";
        else
            cout << "冰冰商业价值相同比西施大。\n";
}

重载左移运算符

重载左移运算符(<<)用于输出自定义对象的成员变量
只能使用非成员函数版本。
如果要输出对象的私有成员,可以配合友元一起使用

#include <iostream>         // 包含头文件。
using namespace std;        // 指定缺省的命名空间。

class CGirl       // 超女类CGirl。
{
    friend ostream& operator<<(ostream& cout, const CGirl& g);
    string    m_name;   // 姓名。
    int         m_xw;        // 胸围。
    int         m_score;    // 评分。
public:
    // 默认构造函数。
    CGirl() { m_name = "西施";  m_xw = 87;  m_score = 30; }
    
    // 自我介绍的方法。
    void show() { cout << "姓名:" << m_name << ",胸围:" << m_xw << ",评分:" << m_score << endl; }
};

ostream& operator<<(ostream& cout, const CGirl& g)
{
    cout << "姓名:" << g.m_name << ",胸围:" << g.m_xw << ",评分:" << g.m_score;
    return cout;
}

int main()
{
    CGirl g;
    cout << g << endl;
}

成员函数的写法。。。(输出数据的话,不符合正常的使用逻辑)

#include <iostream>         // 包含头文件。
using namespace std;        // 指定缺省的命名空间。

class CGirl       // 超女类CGirl。
{
    string    m_name;   // 姓名。
    int         m_xw;        // 胸围。
    int         m_score;    // 评分。
public:
    // 默认构造函数。
    CGirl() { m_name = "西施";  m_xw = 87;  m_score = 30; }
    
    // 自我介绍的方法。
    void show() { cout << "姓名:" << m_name << ",胸围:" << m_xw << ",评分:" << m_score << endl; }

    ostream& operator<<(ostream& cout)
{
    cout << "姓名:" << this->m_name << ",胸围:" << this->m_xw << ",评分:" << this->m_score;
    return cout;
}
};


int main()
{
    CGirl g;
    g<<cout <<  endl;
}

重载下标运算符

返回值类型 &perator[](参数);
const 返回值类型 &operator[](参数) const;

使用第一种声明方式,[]不仅可以访问数组元素,还可以修改数组元素。
使用第二种声明方式,[]只能访问而不能修改数组元素。

在实际开发中,我们应该同时提供以上两种形式,这样做是为了适应const对象,因为通过const 对象只能调用const成员函数,如果不提供第二种形式,那么将无法访问const对象的任何数组元素。

#include <iostream>         // 包含头文件。
using namespace std;        // 指定缺省的命名空间。

class CGirl       // 超女类CGirl。
{
private:
    string    m_boys[3];       // 超女的男朋友
public:
    string    m_name;          // 姓名。

    // 默认构造函数。
    CGirl() { m_boys[0] = "子都"; m_boys[1] = "潘安"; m_boys[2] = "宋玉"; }
    // 显示全部男朋友的姓名。
    void show() { cout << m_boys[0] << "、" << m_boys[1] << "、" << m_boys[2] << endl; }
    
    string& operator[](int ii)
    {
        return m_boys[ii];
    }
    const string& operator[](int ii) const
    {
        return m_boys[ii];
    }
};

int main()
{
    CGirl g;          // 创建超女对象。
    g[1] = "王麻子";
    cout << "第1任男朋友:" << g[1] << endl;
    g.show();

    cout<<"常对象只能访问常函数。。"<<endl;
    const CGirl g1 = g;
    cout << "第1任男朋友:" << g1[1] << endl;
}

重载赋值运算符

 默认赋值函数, 对成员变量进行浅拷贝。

对象的赋值运算是用一个已经存在的对象,给另一个已经存在的对象赋值。
如果类的定义中没有重载赋值函数,编译器就会提供一个默认赋值函数。
如果类中重载了赋值函数,编译器将不提供默认赋值函数。
语法:

类名 & operator=(const 类名 & 源对象);
#include <iostream>         // 包含头文件。
using namespace std;        // 指定缺省的命名空间。
                     
class CGirl       // 超女类CGirl。
{
public:
    int         m_bh;               // 编号。
    string    m_name;          // 姓名。
    int*        m_ptr;              // 计划使用堆区内存。
                        
    CGirl() { m_ptr = nullptr; }
    ~CGirl() { if (m_ptr)  delete m_ptr;  }
    // 显示全部成员变量。
    void show() { cout << "编号:" << m_bh << ",姓名:" << m_name << ",m_ptr=" << m_ptr <</* ",*m_ptr=" << *m_ptr<< */endl; }
    
    //重载等号运算符
    CGirl& operator=(const CGirl& g)
    {
        if (this == &g) return *this;          // 如果是自己给自己赋值。(this指针的解引用)
        
        if (g.m_ptr == nullptr)    // 如果源对象的指针为空,则清空目标对象的内存和指针。
        {
            if (m_ptr != nullptr) { delete m_ptr; m_ptr = nullptr; }
        }
        else    // 如果源对象的指针不为空。
        {
            // 如果目标对象的指针为空,先分配内存。
            if (m_ptr == nullptr) m_ptr = new int;
            // 然后,把源对象内存中的数据复制到目标对象的内存中。
            memcpy(m_ptr, g.m_ptr, sizeof(int));
        }
                  
        m_bh = g.m_bh; m_name = g.m_name;
        cout << "调用了重载赋值函数。\n" << endl; 
        return *this;
    }
};
                         
int main()
{
    CGirl g1, g2;          // 创建超女对象。
    g1.m_bh = 8; g1.m_name = "西施"; g1.m_ptr = new int(3);
    g1.show();
    g2.show();
              
    g2 = g1;  
    g2.show(); 
    cout << "*g1.m_ptr=" << *g1.m_ptr << ",*g2.m_ptr=" << *g2.m_ptr << endl;
}

重载new&delete运算符

在C++中,使用new时,编译器做了两件事情:
1)调用标准库函数operator new()分配内存; (返回的是申请内存空间的起始地址)
2)调用构造函数初始化内存; (把内存中的值初始化)
使用delete时,也做了两件事情:
1)调用析构函数;
2)调用标准库函数operator delete()释放内存。

为一个类重载new和delete时,尽管不必显式地使用static,但实际上仍在创建 static 成员函数。

为整形变量动态分配内存

#include <iostream>         // 包含头文件。
using namespace std;        // 指定缺省的命名空间。
                   

void* operator new(size_t size)   // 参数必须是size_t(unsigned long long),返回值必须是void*。
{
	void* ptr = malloc(size);        // 申请内存。
	return ptr;
}
                
void operator delete(void* ptr)   // 参数必须是void *,返回值必须是void。
{
	if (ptr == 0) return;       // 对空指针delete是安全的。
	free(ptr);      // 释放内存。
}

int main()
{
    int* p1 = new int(3);
    //int *a=(int *)malloc(sizeof(int)*10);
    cout<<"p1="<<p1<<"  (void*)p1="<<(void*)p1<<"   *p1="<<*p1<<endl;
    delete p1;
    
}

为类动态分配内存

#include <iostream>         // 包含头文件。
using namespace std;        // 指定缺省的命名空间。
                   

void* operator new(size_t size)   // 参数必须是size_t(unsigned long long),返回值必须是void*。
{
	void* ptr = malloc(size);        // 申请内存。
	return ptr;
}
                
void operator delete(void* ptr)   // 参数必须是void *,返回值必须是void。
{
	if (ptr == 0) return;       // 对空指针delete是安全的。
	free(ptr);      // 释放内存。
}

class CGirl
{
public:
    int m_bh;
    int m_xw;

    CGirl(int bh,int xw){
        m_bh = bh;
        m_xw = xw;
        cout<<"调用构造函数"<<endl;
    }
    ~CGirl(){
        cout<<"调用析构函数"<<endl;
    }
};


int main()
{
    // int* p1 = new int(3);
    // //int *a=(int *)malloc(sizeof(int)*10);
    // cout<<"p1="<<p1<<"  (void*)p1="<<(void*)p1<<"   *p1="<<*p1<<endl;
    // delete p1;

    CGirl* p2 =new CGirl(2,2);
    delete p2;
    
}

先调用重载的new函数申请内存,然后调用构造函数
先调用析构函数,再调用重载的delete函数;

重载的new和delete可以是全局函数,也可以是类的成员函数
为一个类重载new和delete时,尽管不必显式地使用static,但实际上仍在创建static成员函数。

#include <iostream>         // 包含头文件。
using namespace std;        // 指定缺省的命名空间。
                   
class CGirl
{
public:
    int m_bh;
    int m_xw;

    CGirl(int bh,int xw){
        m_bh = bh;
        m_xw = xw;
        cout<<"调用构造函数"<<endl;
    }
    ~CGirl(){
        cout<<"调用析构函数"<<endl;
    }

    //是静态方法
    void* operator new(size_t size)   // 参数必须是size_t(unsigned long long),返回值必须是void*。
{
	void* ptr = malloc(size);        // 申请内存。
	return ptr;
}
                
void operator delete(void* ptr)   // 参数必须是void *,返回值必须是void。
{
	if (ptr == 0) return;       // 对空指针delete是安全的。
	free(ptr);      // 释放内存。
}
};


int main()
{
    cout<<"使用的是c++的new和delete"<<endl;
    int* p1 = new int(3);
    //int *a=(int *)malloc(sizeof(int)*10);
    cout<<"p1="<<p1<<"  (void*)p1="<<(void*)p1<<"   *p1="<<*p1<<endl;
    delete p1;

    cout<<"使用的是自定义的new和delete(static成员函数)"<<endl;
    CGirl* p2 =new CGirl(2,2);
    delete p2;
    
}

内存池

重载new和delete函数主要就是为了实现内存池。。
在这里插入图片描述

内存池

  • 预先分配一大块内存空间
  • 提升分配和归还速度
  • 减少内存碎片
#include <iostream>         // 包含头文件。
using namespace std;        // 指定缺省的命名空间。
                  
class CGirl       // 超女类CGirl。
{
public:
	int        m_bh;               // 编号。
	int        m_xw;               // 胸围。
	static char*    m_pool;           // 内存池的起始地址。
                 
	static bool initpool()             // 个初始化内存池的函数。
	{
		m_pool = (char*)malloc(18);           // 向系统申请18字节的内存。
		if (m_pool == 0)  return false;        // 如果申请内存失败,返回false。
		memset(m_pool, 0, 18);                  // 把内存池中的内容初始化为0。
		cout << "内存池的起始地址是:" << (void*)m_pool << endl;
		return true;
	}
               
	static void freepool()                                     // 释放内存池。
	{
		if (m_pool == 0) return;                  // 如果内存池为空,不需要释放,直接返回。
		free(m_pool);                                        // 把内存池归还给系统。
		cout << "内存池已释放。\n";
	}
               
	CGirl(int bh, int xw) { m_bh = bh, m_xw = xw;  cout << "调用了构造函数CGirl()\n"; }
	~CGirl() { cout << "调用了析构函数~CGirl()\n"; }
             
	void* operator new(size_t size)   // 参数必须是size_t(unsigned long long),返回值必须是void*。
	{
		if (m_pool[0] == 0)      // 判断第一个位置是否空闲。
		{
			cout << "分配了第一块内存:" << (void*)(m_pool + 1) << endl;
			m_pool[0] = 1;         // 把第一个位置标记为已分配。
			return m_pool + 1;  // 返回第一个用于存放对象的址。
		}
		if (m_pool[9] == 0)          // 判断第二个位置是否空闲。
		{
			cout << "分配了第二块内存:" << (void*)(m_pool + 9) << endl;
			m_pool[9] = 1;             // 把第二个位置标记为已分配。
			return m_pool + 9;      // 返回第二个用于存放对象的址。
		}
		
		// 如果以上两个位置都不可用,那就直接系统申请内存。
		void* ptr = malloc(size);        // 申请内存。
		cout << "申请到的内存的地址是:" << ptr << endl;
		return ptr;
	}
              
	void operator delete(void* ptr)   // 参数必须是void *,返回值必须是void。
	{
		if (ptr == 0) return;      // 如果传进来的地址为空,直接返回。
                
		if (ptr == m_pool + 1)      // 如果传进来的地址是内存池的第一个位置。
		{
			cout << "释放了第一块内存。\n";
			m_pool[0] = 0;              // 把第一个位置标记为空闲。
			return;
		}
                
		if (ptr == m_pool + 9)      // 如果传进来的地址是内存池的第二个位置。
		{
			cout << "释放了第二块内存。\n";
			m_pool[9] = 0;              // 把第二个位置标记为空闲。
			return;
		}
                 
		// 如果传进来的地址不属于内存池,把它归还给系统。
		free(ptr);      // 释放内存。
	}
};
                      
char* CGirl::m_pool = 0;       // 初始化内存池的指针。
                  
int main()
{           
	// 初始化内存池。
	if (CGirl::initpool()==false) { cout << "初始化内存池失败。\n"; return -1; }

	CGirl* p1 = new CGirl(3, 8);       // 将使用内存池的第一个位置。
	cout << "p1的地址是:" << p1 << ",编号:" << p1->m_bh << ",胸围:" << p1->m_xw << endl;
                  
	CGirl* p2 = new CGirl(4, 7);       // 将使用内存池的第二个位置。
	cout << "p2的地址是:" << p2 << ",编号:" << p2->m_bh << ",胸围:" << p2->m_xw << endl;
                    
	CGirl* p3 = new CGirl(6, 9);       // 将使用系统的内存。
	cout << "p3的地址是:" << p3 << ",编号:" << p3->m_bh << ",胸围:" << p3->m_xw << endl;
                 
	delete p1;    // 将释放内存池的第一个位置。
                 
	CGirl* p4 = new CGirl(5, 3);        // 将使用内存池的第一个位置。
	cout << "p4的地址是:" << p4 << ",编号:" << p4->m_bh << ",胸围:" << p4->m_xw << endl;
        
	delete p2;    // 将释放内存池的第二个位置。
	delete p3;    // 将释放系统的内存。
	delete p4;    // 将释放内存池的第一个位置。
                
	CGirl::freepool();     // 释放内存池。
}

重载括号运算符

括号运算符重载函数的语法:

返回值类型 operator()(参数列表);

 括号运算符必须以成员函数的形式进行重载。
 括号运算符重载函数具备普通函数全部的特征。
 如果函数对象与全局函数同名,按作用域规则选择调用的函数。

#include <iostream>         // 包含头文件。
using namespace std;        // 指定缺省的命名空间。
           
void show(string str)    // 向超女表白的函数。
{
	cout << "普通函数:" << str << endl;
}
          
class CGirl      // 超女类。
{
public:
	void operator()(string str)    // 向超女表白的函数。
	{
		cout << "重载函数:" << str << endl;
	}
};
           
int main()
{
	CGirl show;
    cout<<"::调用全局函数"<<endl;
	::show("我是一只傻傻鸟。");

    cout<<"括号运算符重载(调用成员函数):"<<endl;
	show("我是一只傻傻鸟。");
}

重载一元运算符

可重载的一元运算符。
1)++ 自增 2)-- 自减 3)! 逻辑非 4)& 取地址
5)~ 二进制反码 6)* 解引用 7)+ 一元加 8) - 一元求反

重载自增运算符的成员函数版本

C++ 规定,重载++或–时,如果重载函数有一个int形参,编译器处理后置表达式时将调用这个重载函数。

#include <iostream>         // 包含头文件。
using namespace std;        // 指定缺省的命名空间。
          
class CGirl       // 超女类CGirl。
{
public:
    string    m_name;     // 姓名。
    int         m_ranking;  // 排名。
               
    // 默认构造函数。
    CGirl() { m_name = "西施";  m_ranking = 5; }
    // 自我介绍的方法。
    void show() const { cout << "姓名:" << m_name << ",排名:" << m_ranking << endl; }
    CGirl & operator++()         // ++前置的重载函数。
    {
        m_ranking++; return *this;
    }
    CGirl operator++(int)     // ++后置的重载函数。
    {
        CGirl tmp = *this;
        m_ranking++; 
        return tmp;   //返回临时对象
    }
};
                
int main()
{
    CGirl g1,g2;        // 创建超女对象。
    int ii=5 , jj=5;
    int xx = ++(++(++ii));        cout << "xx=" << xx << ",ii=" << ii << endl;
    int yy = jj++;                       cout << "yy=" << yy << ",jj=" << jj << endl;
    CGirl g3 = ++(++(++g1));   cout << "g3.m_ranking=" << g3.m_ranking << ",g1.m_ranking=" << g1.m_ranking << endl;
    CGirl g4 = g2++;                   cout << "g4.m_ranking=" << g4.m_ranking << ",g2.m_ranking=" << g2.m_ranking << endl;
    // g2.show();
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值