C++基础

一,C++对C一些扩展的学习

1,namespace使用和注意点

namespace的定义的

1,namepspace命名空间的里面变量的作用域声明 必须是全局变量

	namespace LOL
	{
		const int a = 90;  //声明成全局变量
		void test();
	}

2, 命名空间存在的意义是避免二义性

解释:就是变量的在不同的命名空间就前面加上命名空间, 在C语言中这样的定义使用会重名

3,命名空间可以有变量,函数,结构体,类

4,命名空间可以圈套命名空间

	namespace LOL1
	{
		int a = 90;
		namespace chen
		{
			int b = 80;
		}
	}
	//命名空间取别名
	namespace che = LOL1;

5,命名空间可以后期扩展, 同名的不会覆盖 而是合并

6,命名空间可以匿名

7,命名空间可以起别名

2,using声明以及using编译指令

using 声明碰到函数重载

	namespace A{
	void func(){}
	void func(int x){}
	int  func(int x,int y){}
	}
	void test(){
		using A::func;
		func();
		func(10);
		func(10, 20);
	}
3,C++ 对C的增强
1,全局变量检测的增强

下面代码在C中可以C++不可以

	int a;
	int a = 80; 
2.函数检测
1.参数类型检测
	//函数在C语言中不用写明函数参数的类型而在C++中必须写类型
	int myswap(a, b);  
2.返回值的检测

在C语言中可以不用写函数的返回值编译器会waring ,C++必须要有返回值

	int myswap(a, b)
	{
	};
3,函数调用 传参个数

在C语言中可以传入多个参数,在C++中可以传多个参数

	int myswap(int a, int b);

	int main(void)
	{
		myswap(89, 90, 89, 89); //在C语言中可以传入多个参数
	return 0;
	}
3,类型转换增强

C++中malloc后必须转换为 需要的类型

4,struct增强
1,C++中可以放函数
2,C++中使用结构体, 可以省略关键字
3,bool类型
   sizeof bool = 1
4,三目运算符增强
C++中返回 变量 可以继续作为左值运算
	int a = 10;
	int b = 20;
	printf("ret:%d\n", a > b ? a : b);
	//思考一个问题,(a > b ? a : b) 三目运算表达式返回的是什么?

	cout << "b:" << b << endl;
	//返回的是左值,变量的引用
	(a > b ? a : b) = 100;//返回的是左值,变量的引用
	cout << "b:" << b << endl;

三目运算的本质是:

	*(a > b ? &a : &b ) = 100;
5,const增强
1,C和C++对const处理的方式

C语言中 局部的const变量 会分配内存, 可以通过指针间接修改,为常量,不许初始化数组

C++中局部的const 会放到符合表中,不可以通过指针修改到本体,可以作为为常量 初始化数组

const在C语言中默认是外部链接,可以在其他文件中进行访问

const在C++中 默认是内部链接,需要利用extern提供作用域,改成外部链接

4,引用的基本语法

引用实际是变量的别名吧了

	int u = 90;
	int const *p = u;
1,语法

语法:类型 &别名 = 原名

2,引用必须要初始化 一旦初始化后就不可以修改指向
	int a1 = 90;
	int &b1 = a1;
	int &b1 = a; //err
3,对数组建立引用的操作
	int arr[] = { 4, 45, 454, 34, 9 };
	//方法一:
	int(&aprr)[5] = arr;
	int i;
	for (i = 0; i < 5; i++)
		cout << aprr[i] << endl;

	//方法二typedef
	typedef int parr[5];
	parr& p = arr;
	for (i = 0; i < 5; i++)
		cout << p[i] << endl;
4,函数参数的是引用
	//引用的使用
	void set_name(char* &name)  //实际还是地址引用
	{
		n_name = name;
	}

二,函数重载和类的封装

1,C++函数的默认参数
1,语法:

语法: 类型 变量名称 = 默认值

	void load(int a = 90000, int b = 100) ///默认值
	{
		cout << "a = " << a << "b = " << b << endl;
	}
	int main(void)
	{
		load(3, 9);   //
		system("pause");
		return 0;
	}

默认参数会被转过去的值输替代

运行效果图

2,参数中有一个参数有了默认值, 那该位置开始从左到右都必须有默认值

例子:

	void load(int a, int b = 90, int c = 1000, int d = 440)
	{
		cout << "a = " << a << "b = " << b << "c = " << c 
			<< "d = " << d << endl;
	}

	int main(void)
	{
		load(3, 4, 5, 6);  //参数
		system("pause");
		return 0;
	}

3,当函数的声明和实现中, 只能有一个出现默认参数
	void load(int a, int b);

	void load(int a, int b, int c, int d);
2,占位符参数

占位符不能使用在头文件中, 占位符是默认值相当于没有

例子:

	//占位符
	void placeholder2(int a, int = 90)  //占位符 int = 90
	{
		cout << "a = " << a << endl;
	}
	
	int main(void)
	{
		//占位符
		placeholder2(9000);
		system("pause");
		return 0;
	}
3,函数重载
  1. 在同一作用域下
  2. 函数的参数不同, 或者类型不同, 或者顺序不同
  3. 函数的返回值不能作为重载的条件
1,重载
	//函数的重载方法名相同参数不同
	void overload()
	{
		cout << "overload()" << endl;
	}
	
	void overload(int a)
	{
		cout << "overload(int a)" << endl;
	}
	
	void overload(int a, int b)
	{
		cout << "overload(int a, int b)" << endl;
	}
2,引用重载

例子1.

	void referen(int& a)  //int const * a //引用是一块内存的空间  //没有内存空间是不可以的
	{
		cout << "a = " << a << endl;
	}
	
	void test()
	{
		int a = 4;
		referen(a);
	}

例子2.

	void referen2(const int &a)  //const int cont * a
	{
		cout << "a = " << a << endl;
	}
	
	void test03()
	{
		referen2(8);
	}

3,函数重载

函数重载碰到默认参数:注意避免二义性

例子:

	void overload()
	{
		cout << "overload()" << endl;
	}
	
	void overload(int a)
	{
		cout << "overload(int a)" << endl;
	}
	void overload(int a, int b = 9090)
	{
		cout << "overload(int a, int b = 9090)" << endl;
	}
	/*
	void overload(int a, int b)
	{
		cout << "overload(int a, int b)" << endl;
	}*/
	
	int main(void)
	{
		//overload(4);  //err他不知道选择那个一个 
		overload(); //ok
		overload(5, 9); ok
		system("pause");
		return 0;
	}

4,extern "C"的使用
	方法1:

	extern "C" void show(); //声明C函数
	
	方法2:

	#ifndef __cpluscplus
	extern "C" {
	#endif // !__cpluscplus
	 
	
	 }
	 #ifndef __cplusplus
	 #endif // !__cplusplus

5,函数封装
  1. 将属性和行为作为一个整体了表现在生活的数据
  2. 加权限 public, protected, private
  3. C++中struct与class的区别是权限的不同, struct结构体默认是public的,class默认是private属性
6,C的宏定义和C++加强内联函数inline的区别
	#define SUM(a , b) (a + b);
	#define MAX(a, b) (a > b ? a : b)
	int main(void)
	{
		int a = 90, b = 3;
		SUM(++a, b); // (++a + b);
	
		MAX(++a, b); //(++a > b ? ++a : b) //区别 
		return 0;
	}

使用内联函数inline就不会出现++a的现象

#define SUM(a , b) (a + b);
#define MAX(a, b) (a > b ? a : b)
int main(void)
{
int a = 90, b = 3;
SUM(++a, b); // (++a + b);
MAX(++a, b); //(++a > b ? ++a : b) // 区别
return 0;
}

使用内联函数inline就不会出现++a的现象
三,类的深拷贝浅拷贝问题 explicit(隐式法 )的使用

1,类的构造函数和析构函数的虚函数的表示

  1. 括号法 (类名 别名(参数))
  2. 显示法 (类名 别名 = 类名(参数))

3. 隐式法 (类名 别名 = 参数)
3. 赋值的是的const使用 void* getname() const;

2,拷贝函数的使用场景
4. 创建一个类的时候使用拷贝函数
5. 值传递方式会调用拷贝函数
6. 以返回值类 方式调用拷贝函数

#include "../include/Game.h"
Game::Game()
{
cout << "Game 无参构造函数" << endl;
}
void Game::setG(char* name)
{
g_name = name;
}
char* Game::getG() const
{
return g_name;
}
Game::Game(const Game& g)
{
cout << "Game 拷贝构造函数" << endl;
g_name = (char*)malloc(sizeof(g.getG()) + 1);
memset(g_name, 0, sizeof(g.getG()) + 1);
strcpy(g_name, g.getG());
}
Game::~Game()
{
cout << "Game 析构函数" << endl;
// 释放内存
/*if (g_name != NULL)
free(g_name);
g_name = NULL;*/
}

Phone

#include "../include/Phone.h"
void Phone::setp(char* name)
{
p_name = name;

}
char* Phone::getP()const
{
return p_name;
}
Phone::Phone()
{
cout << "Phone 无参数构造函数" << endl;
}
Phone::Phone(const Phone& p)
{
cout << "Phone 拷贝构造函数" << endl;
p_name = (char*)malloc(sizeof(p.getP()) + 1);
memset(p_name, 0, sizeof(p.getP()) + 1);
strcpy(p_name, p.getP());
}
Phone::~Phone()
{
cout << "Phone 析构函数" << endl;
/*if (p_name != NULL)
free(p_name);
p_name = NULL;*/
}

Person

#include "../include/Person.h"
void Person::setName(char* name)
{
m_name = name;
}
char* Person::getName() const
{
return m_name;
}
void Person::setPhone(Phone& p)
{
m_phone = p;
}
Phone Person::getPhone() const
{
return m_phone;
}
void Person::setGame(Game& g)

{
m_game = g;
}
Game Person::getGame() const
{
return m_game;
}
Person::Person()
{
cout << "Person 无参构造函数" << endl;
}
Person::Person(const Person& p)
{
cout << "Person 拷贝构造函数" << endl;
m_name = (char*)malloc(sizeof(p.getName()) + 1);
strcpy(m_name, p.getName());
m_phone = p.getPhone();
m_game = p.getGame();
}
void Person::isplay()
{
cout << m_name << m_phone.getP() << m_game.getG() << endl;
}
Person::~Person()
{
cout << "Person 析构函数" << endl;
/*if (m_name != NULL)
free(m_name);
m_name = NULL;*/
}

test

#include "../include/Phone.h"
#include "../include/Game.h"
#include "../include/Person.h"

void test()
{
Person p;
p.setName("chen");
Phone p2;
p2.setp(" 小米");

Game g;
g.setG(" 王者荣耀");
p.setPhone(p2);
p.setGame(g);
p.isplay();
}

int main(void)
{
test();
system("pause");
return 0;
}

效果图

深拷贝构造函数使用的时自己要添加 , 不是可以不用写了,编译器已经把写好了

3.explicit隐式法的使用 ,Google推荐使用隐式法的
Google禁止使用隐式法

class Person
{
private:
int m_a;
public:
Person(int a){ this->m_a = a};
};

void test01()
{
Person p = 1; //google 禁止使用隐式法的这样后期维护难
}

Google推荐explicit

class Person
{
private:
int m_a;
public:
explicit Person(int a){ this->m_a = a};
};
void test01()
{
//Person p = 1; //err
Person p(1);
}

//Google 推荐的

4.new, delete
①, malloc 计算分配多少内存要判断是否分配成功
② malloc 不会调用构造函数 而 new会调用构造函数
③ free 不会调用析构函数 delete 会调用析构函数
④ malloc 和 free 配套使用 ,他们都属于库函数
⑤ new 和 delete 配套使用 ,他们属于运算符
⑥ malloc 返回的是 void* 需要强制类型转换 ,而 new返回是该对象的指针,不需要类型转

⑦不要用 void* 接受 new出来的对象,原因是无法进行释放
⑧利用 new创建数组 delete 时候 要加【】 delete [] 数组名

四,引用作为返回值的

  1. 返回引用的函数实际上是被引用的变量的别名
  2. 在作为函数参数和函数的返回值的引用
free_throws & accmulate(free_throws & target,
const free_throws & source)
{
target.attempts += source.attempts;
target.made += source.made;
set_pc(target);
return target;
}

函数accmulate使用有好几种

  1. accmulate(team, one); display(team);
  2. display(accmulate(team, two));
  3. accmulate(accmulate(team, three), four);
  4. dup = accmulate(team, five);
  5. accmulate(dup, five) = team;

2,将 const用于引用返回类型

const free_throws & accmulate(free_throws & target,
const free_throws & source);
那么函数的一些的调用就不可以使用了

  1. accmulate(accmulate(team, three), four);
  2. accmulate(dup, five) = team;

3,将引用用于类对象

string version1(const string & s1,
const string & s2)
{
string temp;
temp = s2 + s1 + s2;
return temp;
}
const string & version2(string & s1,
const string & s2)
{
s1 = s2 + s1 + s2;
return s1;
}
const string & version3(string & s1,
const string & s2)
{
string temp;
temp = s2 + s1 + s2;
return temp;
/*s1 = s2 + s1 + s2;
return s1;*/
}

测试test

void test01()
{
string input;
string copy;
string result;
cout << "Enter a string: ";
getline(cin, input);
copy = input;
cout << "Your string as entered: " << input << endl;
result = version1(input, "***");
cout << "Your string enhanced: " << result << endl;
cout << "Your string enhanced: " << result << endl;
cout << "Your original-string:" << input << endl;
result = version2(input, "###");
cout << "Your string enhanced: " << result << endl;

cout << "Your original string: " << input << endl;
cout << "Resetting original string: \n";
input = copy;
result = version3(input, "@@@"); //err
cout << "Your string enhanced: " << result << endl;
cout << "Your original string: " << input << endl;
}

4,何时使用引用参数
使用引用参数的主要原因有两个

  1. 程序员能够修改调用函数中的数据对象。

  2. 通过传递引用而不是整个数据对象,可以提高程序的运行速度。
    当数据对象较大时(如结构和类对象),第二个原因最重要。这些也是使用指针参数的原因。
    这是有道理的,因为引用参数实际上是基于指针的代码的另一个接口。那么,什么时候应
    使用引用,什么时候使用指针呢?什么时候应按值传递呢?下面是一些指导原则:
    一,对于使用传递的值而不作修改的函数

  3. 如果数据对象很小,如内置数据类型或小型结构,可以按值传递。

  4. 如果数据对象是数组,值使用指针,因为这是唯一的选择,并将指针声明为指向const的指
    针。

  5. 如果数据对象是较大的结构,使用const指针或者const引用,以提高程序的效率。这样可以
    节省复制结构所需的时间和空间。

  6. 如果数据对象是类对象,使用const引用。类设计的语义常常要 求使用引用,这是C++新增
    这项的主要原因。因此,传递类对象参数的标准分数是按引用传递。
    二,对于修改调用函数中数据的函数

  7. 如果数据对象是内置数据类型,则使用指针。如果看到诸如fixit(&x)这样的代码(其中x是

int),则很明显,该函数将修改x。
2. 如果数据对象是数组,则只能使用指针。
3. 如果数据对象是结构,则使用引用或指针。
4. 如果数据对象是类对象,则使用引用。

五,静态,常量,单例模式, this指针和有元

1,静态和常量的关系总结
①静态常量和静态函数的关系

  1. 静态常量必须在类的外面赋值
  2. 静态常量在程序编译阶段就已经赋值了
  3. 静态常量是静态函数来管理的和改变只,类中函数改变只是静态常量一个临时的值
  4. 静态函数是全局的可以访问的

②常量和常量函数的关系

  1. 常量在格式是const int 数据类型;
  2. 常量不可以是不可以修改的,但是要修改可以在声明的时候加上

mutable关键字 是可

修改的

  1. 常函数的格式是 返回值 方法名(参数) const; 的格式
  2. 常函数不可以修改内容的只可以读的工作的有一个例外加上 mutable的变量
  3. 常类只可以访问常函数的因为常类可以修改内容的
    ③静态和常量总结

2,单例模式
说明:单例模式是只有一个实例,所有的其他的都是用同一实例就叫单例模式,而且这个实例当
程序运行起来时存在直到程序结束

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
using namespace std; 
// 使用标准的命名空间
class Printer
{
private:
    int sum;
    static Printer* singlePrinter;
    Printer()
    {

        cout << " 无参构造函数" << endl;
        sum = 0;
    }
    // 拷贝函数的
    Printer(const Printer& p)
    {
        cout << " 拷贝构造函数" << endl;
    }
public:
    // 得到实例
    static Printer* getInstanect()
    {
        return singlePrinter;
    }
    void getShowTest(string name)
    {
        cout << name << endl;
        sum = 1 + sum;
        cout << sum << endl;
    }
    ~Printer()
    {
        cout << " 析构函数" << endl;
    }

};
// 实例化
Printer* Printer::singlePrinter = new Printer;

void test01()
{
    Printer* p1 = Printer::getInstanect();
    p1->getShowTest(" 陈丽");
    p1->getShowTest(" 王蓉");
    Printer* p2 = Printer::getInstanect();
    p2->getShowTest(" 王盼盼");
    if (p1 == p2)
        cout << " 相同" << endl;
    else
        cout << " 不相同" << endl;
}
int main(void)

{
    test01();
    system("pause");
    return 0;
}

3,*this指针的使用

Person& getAdd(int age)
{
this->setAge(this->m_age + age);
return *this;
}

4,有元函数和有元类
声明的格式分别是

  1. 有元函数: friend 返回类型 方法名 (参数);
  2. 有元类: friend class 类名;
  3. 有元类中有元函数:friend 作用域::方法名(参数);
class Person
{
friend void test();
private:
int m_a;
char* che;
};
void test()
{
Person p;
p.m_a = 90;// 可以访问,赋值操作
cout << p.m_a << endl;
}

六,数组类的封装,运算符重载和智能 this指针的使用

1,数组类的封装

UML的结构图
文件的声明:


class MyArray
{
public:
    /* 数组类的拷贝构造函数 */
    MyArray(const MyArray&arr);
    /* 数组类的有参构造函数参构造函数 */
    MyArray(int capactity);
    /* 数组类的析构函数 */
    ~MyArray();
    /* 数组类的无参构造函数 */
    void Myarray(void);
    /* 在数组的尾巴插入数据val */
    void Tail_pash(int val);
    /* 按照位置index 位置改变数组的index 位置的值 */
    void set_arr_val(int index, int val);
    /* 获取数组index 值 */
    int getValData(int index);
    /* [] 运算符重载 index */
    Myarray& operator[](int index);
    /* 获取数组类的长度 */
    int getLength(void);
protected:
private:
    /* 数组的已经有的数据大小size */
    int m_Size;
    /* 数组类的首地址 */
    int* m_Address;
    /* 数组类的容量大 */
    int m_Capatity;
};

2,运算符重载
① ++,–运算符重载
我发现一个问题就是引用作为返回值时在 gcc上是报错的
前置++,–的格式

对象名& operator++()

{
this-> 变量++ ;
return *this;
}
后置++,--的格式是要找到一个中间变量
对象名 operator++(int)

{
对象名 temp;

temp. 变量 = this-> 变量;
this-> 变量++;
return temp;
}

② <<,>>运算符操作
一般使用全局函数作为<<,>> 要声明成有元函数
格式:friend ostream& operator<<(ostream& os, 对象名& p);

操作:

ostream& operator<<(ostream& os, 对象名& p)
{
os << p. 变量 ;
return os;
}

3,智能指针 this的使用

UML图
头文件声明: pointer

#include <Pointer.h>
class SmartPointer
{
public:
    /* SmartPointer 析构函数释放Pointer 的堆上内存 */

    ~SmartPointer();
    /* SmartPointer 构造函数 */
    SmartPointer(Pointer* p);
    /* -> 指针的重载 */
    Pointer* operator->(void);
    /* * 管理Pointer 指针函数 */
    Pointer& operator*(void);
protected:
private:
    Pointer* poiner;

};

重点:拷贝构造函数只在初始化的时候会调用
七 .关系运算符的封装 MyString和继承的静态( static),构造和析构,
虚继承 virtual偏移量

1,关系运算符重载 =,>>,<<

/* << 运算符重载打印
friend ostream&
/* >> 赋值的操作的
friend istream&

*/
operator<<(const MyString& my_str);
*/
operator>>(const MyString& my_str);

总结: &&, ||这样的运算符是可以重载的但是重载后就没有本身的一些性质

2,MyString类的封装
UML结构体

头文件的声明:


#if !defined(__MyString_MyString_h)
#define __MyString_MyString_h
class MyString
{
public:
    /* 有参构造函数 */
    MyString(const char* str);
    /* Mystring 类的拷贝函数
    * 深拷贝字符串char* */
    MyString(const MyStirng&* my_str);
    /* 析构函数 释放内存 */
    ~MyString();
    /* 分为两种情况赋值操作
    * 1 ,char* 类型
    * 2 ,对象 类型的赋值操作 */
    MyString& operator=(char* str);
    /* 对象赋值的操作 */
    MyString& operator=(const MyString& my_str);
    /* 取出字符串中的index 的字符的操作 */
    char operator[](const int index);
    /* 字符串拼接的也两种情况
    * 1 ,char* 拼接
    * 2 ,对象类型拼接 */
    MyString operator+(const char* str);
    /* 字符串拼接
    * 对象拼接的情况 */
    MyString operator+(const MyString& my_str);
    /* 比较两个是否相同分为两种情况

    * 1 ,char* 比较
     * 2 ,对象 比较 */
    bool operator==(const char* str);
    /* 对象的比较 */
    bool operator==(const MyString& my_str);
protected:
private:
    /* << 运算符重载打印 */
    friend ostream& operator<<(const MyString& my_str);
    /* >> 赋值的操作的 */
    friend istream& operator >> (const MyString& my_str);
    /* 字符串的大小 */
    int m_size;
    /* 字符串的地址 */
    char* m_String;

};
#endif

3,继承的构造和析构, static
①先调用父类构造再调用子类构造,析构反置
②当子类成员函数和父类成员函数名相同时,子类会隐藏父类中成员函数。
解决的方法:加上作用域

4,多继承中虚继承使用,偏移量
继承中virtual相同的有在C11中以后override, final关键字了


class Animal
{
public:
    int m_age;
};
class Sheep : virtual public Animal
{
};
class Tuo :virtual public Animal
{

};
class SheepTuo : public Sheep, public Tuo
{
};
void test01()
{
    Sheep s;
    s.m_age = 90;
    s.Sheep::m_age = 100;
    cout << s.m_age << endl;
}
int main(void)
{
    test01();
    system("pause");
    return 0;
}

查看继承结构:
cl /d1 reportSingleClassLayout 类名

文件名.cc

八 .多态,重载,重定义,重写

1.多态的继承,虚函数
① 在父类中要把可以重写的声明成虚函数或者纯虚函数子类要重写
②析构函数在父类中要声明 virtual类型子类要重写, 当声明成纯虚析构函数是要在类父类
的外写上析构函数

class Animal
{
public:
    virtual void speack() = 0; // 纯虚函数成员
    virtual ~Animal() = 0; // 纯虚析构函数
                           /*{
                           cout << "Animal 析构函数" << endl;
                           }*/
};
Animal::~Animal()
{
    cout << "Animal 析构函数" << endl;
}

③虚机类表编译器内部原理
结构图
代码:

class Animal
{
public:
    int m_age;
};
class Sheep : virtual public Animal
{
    int m_a;
};
class Tuo :virtual public Animal
{
};
class SheepTuo : public Sheep, public Tuo
{
};
void test01()
{
    Sheep s;
    s.m_age = 90;
    s.Sheep::m_age = 100;
    cout << s.m_age << endl;
}

4.类型转换的安全性
①向上:是子类 -> 父类 动态是安全的
②向下 :父类 -> 子类 不安全的

5.重载 (同一作用域的同名函数 ),重定义 (隐藏 ),重写 (覆盖 )
①重载

  1. 同一个作用域
  2. 参数个数,参数顺序,参数类型不同
  3. 和函数返回值,没有关系
  4. const也可以作为重载条件 //do(const Teacher& t){} do(Teacher& t)

②重定义

1. 有继承
2. 子类(派生类)重新定义父类(基类)的同名成员(非virtual函数)
③ 重写(覆盖)

  1. 有继承
  2. 子类(派生类)重写父类(基类)的virtual函数
  3. 函数返回值,函数名字,函数参数,必须和基类中的虚函数一致

6.接口 interface
定义:

  1. 只有纯虚函数("=0")和静态函数(除了下文提到的析构函数) ,析构
    函数不能是纯虚析构函数

  2. 没有非静态数据成员

  3. 没有定义任何构造函数,如果有,,也不能带有参数,并且必须为
    protected

  4. 如果它是一个子类,也只能从满足上述条件并以Interface为后缀的类继

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值