C++核心编程(黑马笔记)

【使用C++语言 编写CPU多核绑定程序】 【前言 什么是CPU亲和性 如何将CPU亲和性应用到程序中?thread 线程绑定CPU方法 绑定常用函数 taskset命令 参考质料】 阅读详情

C++核心编程(面向对象)

内存分区模型

C++执行时,内存大方向划分为4个区域

  • 代码区:存放函数体的二进制代码,由操作系统管理
  • 全局区:存放全局变量和静态变量以及常量
  • 栈区:由编译器自动分配释放,存放函数的参数值,局部变量等
  • 堆区:由程序员分配和释放,如果程序员不释放,程序结束时由操作系统回收

在这里插入图片描述

程序运行前

程序编译后,生成了exe,未执行程序前

代码区:

​ 存放CPU执行的机器指令

​ **特点:**共享的:频繁执行代码,只需保存一份

​ 只读的:防止程序意外修改

全局区:

​ 存放全局变量和静态变量

​ 包含常量区:存放字符串常量和其他常量

​ 该区域的数据在程序结束后被操作系统释放

示例:

#include <iostream>

using namespace std;

int g_a = 1;
int g_b = 1;

const int g_c = 4;
const int g_d = 4;

int main() {
	int a = 2;
	int b = 2;

	static int s_a = 3;
	static int s_b = 3;

	cout << "局部变量a " << (int)&a << endl;
	cout << "局部变量b " << (int)&b << endl;

	cout << "全局变量a " << (int)&g_a << endl;
	cout << "全局变量b " << (int)&g_b << endl;

	cout << "静态变量a " << (int)&s_a << endl;
	cout << "静态变量b " << (int)&s_b << endl;

	cout << "字符串常量" << (int)&"hello" << endl;

	cout << "全局常量c " << (int)&g_c << endl;
	cout << "全局常量d " << (int)&g_d << endl;

	const int c = 5;
	const int d = 5;

	cout << "局部常量c " << (int)&c << endl;
	cout << "局部常量d " << (int)&d << endl;

	system("pause");

	return 0;
}

程序运行后

栈区:

​ 编译器自动分配释放,存放函数的参数值,局部变量等

​ 注意:不要返回局部变量的地址,栈区开辟的数据由编译器自动释放

示例:

# include <iostream>

using namespace std;

int* func() {
	int a = 100;
	return &a;
}

int main() {

	int* p = func();
	cout << *p << endl;
	cout << *p << endl;
	cout << *p << endl;

	system("pause");
	return 0;
}

注意 VS2022(64位)地址一直保留

堆区:

​ 由程序员分配和释放,如果程序员不释放,程序结束时由操作系统回收

​ 主要利用new在堆区开辟内存

示例:

# include <iostream>

using namespace std;

int* func() {
	int* p = new int(10);
	return p;
}

int main() {
	// 指针本质上也是局部变量,放在栈上,指针保存的数据放在堆区
	int* p = func();
	cout << *p << endl;
	cout << *p << endl;

	system("pause");
	return 0;
}

new

  • new操作符在堆区开辟数据
  • 手动释放使用delete
  • new的数据返回对应类型的指针

示例:

# include <iostream>

using namespace std;

int* func() {
	int* p = new int(10);
	return p;
}

void test01() {
	int* p = func();
	cout << *p << endl;
	cout << *p << endl;
	delete(p);
	//cout << *p << endl;
}

void test02() {
	int* arr = new int[10];
	for (int i = 0; i < 10; i++) {
		arr[i] = i;
	}
	for (int i = 0; i < 10; i++) {
		cout << arr[i] << endl;
	}
	delete[] arr;
}

int main() {

	test01();
	test02();

	system("pause");
	return 0;
}

引用

基本使用

  • 给变量起别名
  • 数据类型 &别名 = 原名
  • 引用必须初始化
  • 一旦初始化,就不可更改

示例:

# include <iostream>

using namespace std;


int main() {
	int a = 10;
	int& b = a;

	cout << a << endl;
	cout << b << endl;

	b = 100;
	cout << a << endl;
	cout << b << endl;

	int c = 20;
	b = c;

	cout << a << endl;
	cout << b << endl;
	cout << c << endl;

	system("pause");
	return 0;
}

函数

  • 引用做函数参数

  • 引用做函数返回值

  • 不要返回局部变量的引用

  • 函数的调用可以作为左值

示例:

# include <iostream>

using namespace std;

void swap(int& a, int& b) {
	int temp = a;
	a = b;
	b = temp;
}

int& test01() {
	int a = 10;
	return a;
}

int& test02() {
	static int a = 90;
	return a;
}

int main() {
	int a = 10;
	int b = 20;
	swap(a, b);
	cout << a << endl;
	cout << b << endl;

	int& ref1 = test01();
	cout << ref1 << endl;
	cout << ref1 << endl;

	int& ref2 = test02();
	cout << ref2 << endl;
	cout << ref2 << endl;
	test02() = 190;
	cout << ref2 << endl;
	cout << ref2 << endl;

	system("pause");
	return 0;
}

本质

本质上是指针常量

int& ref = a 相当于 int* const ref = &a

ref = 20 相当于 *ref = 20


常量引用

**作用:**常量引用主要用来修饰形参,防止误操作

在函数形参列表中,可以加const修饰形参,防止形参改变实参

示例:

# include <iostream>

using namespace std;

void show(const int& val) {
	cout << val << endl;
}

int main() {
	const int& ref = 10;// 相当于 int temp = 10; const int& ref = temp;
	// 加上 const 变成只读 不可修改
	int a = 100;
	show(a);

	system("pause");
	return 0;
}

函数高级

默认参数

语法:返回值类型 函数名 (参数 默认值)

注意:

  • 如果某个位置有了默认参数,从这个位置往后,从左往右都必须有默认值
  • 函数声明有了默认参数,函数实现不能有默认参数(只能有一个有默认参数)

示例:

# include <iostream>

using namespace std;

int sum(int a, int b = 20, int c = 30) {
	return a + b + c;
}

int main() {
	cout << sum(10) << endl;
	cout << sum(10, 30) << endl;

	system("pause");
	return 0;
}

占位参数

语法:返回值类型 函数名 (数据类型){}

示例:

# include <iostream>

using namespace std;

int sum(int a, int) {
	return a;
}

int main() {
	cout << sum(10, 30) << endl;

	system("pause");
	return 0;
}

函数重载

**作用:**函数名可以相同,提高复用性

满足条件:

  • 同一个作用域
  • 函数名称相同
  • 函数参数类型不同或者个数不同或者顺序不同

**注意:**函数重载的返回值不可以作为函数重载的条件

示例:

# include <iostream>

using namespace std;

void sum() {
	cout << "aaa" << endl;
}

void sum(int a) {
	cout << "int" << endl;
}

void sum(double a) {
	cout << "double" << endl;
}

void sum(double a, int b) {
	cout << "double,int" << endl;
}

void sum(int a, double b) {
	cout << "int,double" << endl;
}
//注意事项
//int sum(int a, double b) {
//	cout << "int,double" << endl;
//}

int main() {
	sum();
	sum(10);
	sum(10.0);
	sum(3.14, 10);
	sum(10, 3.13);

	system("pause");
	return 0;
}

注意事项:

# include <iostream>
using namespace std;
//引用作为重载的条件
void func(int& a) {
	cout << "void func(int& a)" << endl;
}

void func(const int& a) {
	cout << "void func(const int& a)" << endl;
}
//函数重载碰到默认参数
void func2(int a, int b = 10) {
	cout << "a,b" << endl;
}

void func2(int a) {
	cout << "a" << endl;
}

int main() {
	int a;
	func(a);
	func(10);

	//func2(10);

	system("pause");
	return 0;
}

类和对象

封装

意义:

  • 将属性和行为作为一个整体
  • 将属性和行为加以权限控制

示例:

# include <iostream>
using namespace std;

class Circle{
public:
	//属性
	int r;
	//行为
	double func() {
		return 2 * 3.14 * r;
	}
	void setR(int R) {
		r = R;
	}
};

int main() {
	Circle c;
	c.r = 10;
	cout << c.func();
	return 0;
}

访问权限:

public类内可以访问类外可以访问
protected类内可以访问类外不可访问可以访问父类的保护内容
private类内可以访问类外不可访问不可以访问父类的私有内容

示例:

# include <iostream>
# include <string>
using namespace std;

class Person{
public:
	string name;
protected:
	string car;
private:
	string password;
};

int main() {
	Person nb;
	nb.name = "nb";
	//nb.car;
	//nb.password;
	cout << nb.name;
	return 0;
}

struct与class的区别:

  • struct默认为public
  • class默认为private

成员属性设置为私有:

  • 自己控制读写权限
  • 检测数据有效性

示例:

# include <iostream>
# include <string>
using namespace std;
class Person{
public:
	void setname(string name) {
		m_name = name;
	}

	string getname() {
		return m_name;
	}

	void setage(int age) {
		if (age < 0 || age > 160) {
			cout << "error";
			return;
		}
		m_age = age;
	}

	int getage() {
		return m_age;
	}

	void setid(int id) {
		m_id = id;
	}
private:
	string m_name;
	int m_age = 8;
	int m_id = 1;
};
int main() {
	Person p;
	p.setname("王小明");
	cout << p.getname() << " " << p.getage() << endl;
	return 0;
}

对象的初始化和清理

构造函数和析构函数:

  • 构造函数:创建对象时为对象的成员赋值,由编译器自动调用
  • 析构函数:对象销毁前系统自动调用,执行清理工作

我们不提供析构和构造的话,编译器提供的是空实现。

构造函数语法:类名(){}

析构函数语法:~类名(){}

相同点:

  • 没有返回值也不写void
  • 函数名称与类名相同
  • 无需手动调用,并且只会调用一次

不同点:

  • 构造函数可以有参数,可以发生重载
  • 析构函数不可以有参数,不可以发生重载
# include <iostream>
using namespace std;

class Person{
public:
	Person() {
		cout << "1" << endl;
	}
	~Person() {
		cout << "2" << endl;
	}
};

void test01() {
	Person p;
}

int main() {
	//test01();
	Person p;
	system("pause");
	return 0;
}

构造函数的分类和调用:

两种分类方式:

  • 参数:有参构造和无参构造
  • 类型:普通构造和拷贝构造

三种调用方式:

  • 括号法
  • 显示法
  • 隐式转换法
# include <iostream>
using namespace std;

class Person{
public:
	Person() {
		cout << "无参构造" << endl;
	}
	Person(int a) {
		age = a;
		cout << "有参构造" << endl;
	}
	Person(const Person& p) {
		age = p.age;
		cout << "拷贝构造" << endl;
	}
	~Person() {
		cout << "析构" << endl;
	}
	int age;
};

void test01() {
	//括号法
	//Person p1;
	//Person p2(10);
	//Person p3(p2);
	//注意:
	//调用默认构造函数时,不要加(),编译器会认为是一个函数的声明

	//cout << "p2年龄为:" << p2.age << endl;
	//cout << "p3年龄为:" << p3.age << endl;

	//显示法
	Person p1;
	Person p2 = Person(10);
	Person p3 = Person(p2);
	//Person(10) 匿名对象 当前行结束 系统自动回收
	//Person(p2) 不能利用拷贝构造函数 初始化匿名对象 
	//			编译器会认为 Person (p3) 相当于 Person p3

	//隐式转换
	Person p4 = 20; // 相当于 Person p4 = Person(20)
	Person p5 = p4;
}

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

拷贝构造函数的调用时机:

三种情况:

  • 使用一个已经创建完毕的对象来初始化一个新对象
  • 值传递的方式给函数参数传值
  • 值方式返回局部对象
# include <iostream>
using namespace std;

class Person{
public:
	Person() {
		cout << "无参构造" << endl;
	}
	Person(int a) {
		age = a;
		cout << "有参构造" << endl;
	}
	Person(const Person& p) {
		age = p.age;
		cout << "拷贝构造" << endl;
	}
	~Person() {
		cout << "析构" << endl;
	}
	int age;
};

//使用一个已经创建完毕的对象来初始化一个新对象
void test01() {
	
	Person p1(20);
	Person p2(p1);
	cout << "p2年龄为:" << p2.age << endl;
}

//值传递的方式给函数参数传值
void doWork02(Person p) {

}

void test02() {
	Person p;
	doWork02(p);
}

//值方式返回局部对象
Person doWork03() {
	Person p1;
	return p1;
}

void test03() {
	Person p = doWork03();
}

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

构造函数调用规则:

默认情况下,C++编译器至少给一个类添加3个函数

  1. 默认构造函数(无参,函数体为空)
  2. 默认析构函数(无参,函数体为空)
  3. 默认拷贝构造函数,拷贝属性值

调用规则:

  • 如果用户定义有参构造函数,C++不在提供默认无参构造,但是会提供默认拷贝构造
  • 如果用户定义拷贝构造函数,C++不会再提供其他构造函数
# include <iostream>
using namespace std;

class Person{
public:
	//Person() {
	//	cout << "无参构造" << endl;
	//}
	Person(int a) {
		age = a;
		cout << "有参构造" << endl;
	}
	//Person(const Person& p) {
	//	age = p.age;
	//	cout << "拷贝构造" << endl;
	//}
	~Person() {
		cout << "析构" << endl;
	}
	int age;
};

//void test01() {
//	Person p1;
//	p1.age = 10;
//	Person p2(p1);
//	cout << "p2年龄为:" << p2.age << endl;
//}

//如果用户定义有参构造函数,C++不在提供默认无参构造,但是会提供默认拷贝构造
void test02() {
	Person p(28);
	Person p2(p);
	cout << "p2年龄为:" << p2.age << endl;
}

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

深拷贝与浅拷贝:

  • 浅拷贝:简单赋值拷贝操作
  • 深拷贝:堆区重新申请空间,进行拷贝
# include <iostream>
using namespace std;

class Person{
public:
	Person() {
		cout << "无参构造" << endl;
	}
	Person(int a,int h) {
		age = a;
		height = new int(h);
		cout << "有参构造" << endl;
	}
	Person(const Person& p) {
		age = p.age;
		//height = p.height; // 编译器浅拷贝
		height = new int(*p.height);
		cout << "拷贝构造" << endl;
	}
	~Person() {
		if (height != NULL) {
			delete height;
			height = NULL;
		}
		cout << "析构" << endl;
	}
	int age;
	int* height;
};

void test01() {
	Person p1(18, 180);
	cout << "p1年龄为:" << p1.age << " p1身高为:" << *p1.height << endl;
	Person p2(p1);
	cout << "p2年龄为:" << p2.age << " p2身高为:" << *p2.height << endl;
}

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

初始化列表:

语法:构造函数(): 属性1(值1),属性2(值2) ...{}

# include <iostream>
using namespace std;

class Person{
public:
	Person(int pa, int pb, int pc) : a(pa), b(pb), c(pc) {

	}
	int a;
	int b;
	int c;
};

void test01() {
	Person p(10, 20, 30);
	cout << p.a << " " << p.b << " " << p.c << endl;
}

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

对象成员:

class A {}
class B {
    A a;
}

示例:顺序:手机构造->人构造->人析构->手机析构

# include <iostream>
# include <string>
using namespace std;

class Phone {
public:
	Phone(string name) {
		m_Pname = name;
		cout << "手机构造" << endl;
	}
	~Phone() {
		cout << "手机析构" << endl;
	}
	string m_Pname;
};

class Person{
public:
	Person(string name, string Pname) : m_name(name), m_phone(Pname) {
		cout << "人构造" << endl;
	}
	~Person() {
		cout << "人析构" << endl;
	}
	string m_name;
	Phone m_phone;
};

void test01() {
	Person p("张三", "苹果");
}

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

静态成员:

静态成员变量:

  • 所有对象共享一份数据
  • 编译阶段分配内存
  • 类内声明,类外初始化

静态成员函数:

  • 所有对象共享同一个函数
  • 只能访问静态成员变量

示例1:

# include <iostream>
# include <string>
using namespace std;

class Person{
public:
	static int a;
private:
	static int b;
};

int Person::a = 10;
int Person::b = 20;

void test01() {
	Person p1;
	cout << p1.a << endl;
	Person p2;
	p2.a = 20;
	//两种访问方式
	cout << p1.a << endl;
	cout << Person::a << endl;
	//cout << Person::b << endl;
}

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

示例2:

# include <iostream>
# include <string>
using namespace std;

class Person{
public:
	static void func() {
		a = 100;
		//b = 200; 可能有多个对象包含不同的b 不知道修改哪个b
		cout << "static void func调用" << endl;
	}
	int b;
	static int a;
};

int Person::a = 1000;

void test01() {
	Person p1;
	p1.func();
	Person::func();
}

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

C++对象模型和this指针

成员变量和成员函数分开存储:

# include <iostream>
# include <string>
using namespace std;

class Person {
	static int a; // 不属于类对象
	int b; // 属于类对象
	void func(){} // 不属于类对象
	static void fun(){} //不属于类对象
};

int Person::a = 1;

void test01() {
	//空对象sizeof为1
	Person p;
	cout << sizeof(p) << endl; 
}

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

this指针:

this指针指向被调用的成员函数所属的对象

this指针是隐含每一个非静态成员函数内的一种指针

this指针不需要定义,直接使用即可

用途:

  • 形参和成员变量同名时,可用this指针区分
  • 在类的非静态成员函数中返回对象本身,可使用return *this
# include <iostream>
# include <string>
using namespace std;

class Person {
public:
	int age;
	Person(int age) {
		this->age = age;
	}

	//返回Person 值传递调用拷贝构造函数 创建一个新对象 p2-p2'-p2''-p2'''
	Person& PersonAddAge(Person& p) {
		this->age += p.age;
		return *this;
	}
};

void test01() {
	Person p1(10);
	Person p2(10);
	p2.PersonAddAge(p1).PersonAddAge(p1).PersonAddAge(p1);
	cout << p2.age << endl;
}

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

空指针访问成员函数:

# include <iostream>
# include <string>
using namespace std;

class Person {
public:
	void show1() {
		cout << "1" << endl;
	}

	void show2() {
		if (this == NULL) {
			return;
		}
		cout << this->b << endl;
	}

	int b;
};

void test01() {
	Person* p = NULL;
	p->show1();
	p->show2();
}

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

const修饰成员函数:

常函数:

  • 成员函数后加const
  • 不可以修改成员属性
  • 加关键字mutable后,在常函数中可以修改

常对象:

  • 声明对象前加const
  • 只能调用常函数
# include <iostream>
# include <string>
using namespace std;

class Person {
public:
	//相当于 const Person* const this
	void show() const{
		//this 本质是指针常量 指向不可修改 相当于 Person* const this
		//this = NULL; 
		//this->m_a = 10;
		this->m_b = 20;
	}
	void func(){}
	int m_a;
	mutable int m_b;
};

void test01() {
	Person p1;
	p1.show();
	const Person p2;
	//p2.m_a = 10;
	p2.m_b = 90;
	p2.show();
	//p2.func();
}

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

友元

目的:让一个函数或者类访问另一个类中私有成员

关键字:friend

三种实现:

  • 全局函数
  • 类
  • 成员函数

全局函数:

# include <iostream>
# include <string>
using namespace std;

class Building {
	//全局函数做友元
	friend void test01(Building* b);
public:
	Building() {
		this->m_LivingRoom = "客厅";
		this->m_BedRoom = "卧室";
	}
	string m_LivingRoom;
private:
	string m_BedRoom;
};

void test01(Building *b) {
	cout << b->m_LivingRoom << endl;
	cout << b->m_BedRoom << endl;
}

int main() {
	Building b;
	test01(&b);
	system("pause");
	return 0;
}

类:

# include <iostream>
# include <string>
using namespace std;

class Building;

class GoodGay {
public:
	GoodGay();
	void visit();
	Building* building;
};

class Building {
	//类使用友元
	friend class GoodGay;
public:
	Building() {
		this->m_LivingRoom = "客厅";
		this->m_BedRoom = "卧室";
	}
	string m_LivingRoom;
private:
	string m_BedRoom;
};

GoodGay::GoodGay() {
	building = new Building;
}

void GoodGay::visit() {
	cout << building->m_LivingRoom << endl;
	cout << building->m_BedRoom << endl;
}

void test01() {
	GoodGay g;
	g.visit();
}

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

成员函数:

# include <iostream>
# include <string>
using namespace std;

class Building;

class GoodGay {
public:
	GoodGay();
	void visit1();
	Building* building;
};

class Building {
	//成员函数使用友元
	friend void GoodGay::visit1();
public:
	Building() {
		this->m_LivingRoom = "客厅";
		this->m_BedRoom = "卧室";
	}
	string m_LivingRoom;
private:
	string m_BedRoom;
};

GoodGay::GoodGay() {
	building = new Building;
}

void GoodGay::visit1() {
	cout << building->m_LivingRoom << endl;
	cout << building->m_BedRoom << endl;
}

void test01() {
	GoodGay g;
	g.visit1();
}

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

运算符重载

加法:

# include <iostream>
# include <string>
using namespace std;

class Person {
public:
	Person() {
		this->m_a = 10;
		this->m_b = 20;
	}
	//成员函数重载
	//本质 p3 = p1.operator+(p2)
	//Person operator+(Person& p) {
	//	Person temp;
	//	temp.m_a = p.m_a + this->m_a;
	//	temp.m_b = p.m_b + this->m_b;
	//	return temp;
	//}
	int m_a;
	int m_b;
};

//全局函数重载
//本质 p3 = operator+(p1, p2)
Person operator+(Person& p1, Person& p2) {
	Person temp;
	temp.m_a = p1.m_a + p2.m_a;
	temp.m_b = p1.m_b + p2.m_b;
	return temp;
}

void test01() {
	Person p1;
	Person p2;
	Person p3 = p1 + p2;
	cout << p3.m_a << endl;
	cout << p3.m_b << endl;
}
int main() {
	test01();
	system("pause");
	return 0;
}

左移:

# include <iostream>
# include <string>
using namespace std;

class Person {
public:
	Person() {
		this->m_a = 10;
		this->m_b = 20;
	}
	//成员函数无法实现 p.operator << (cout) 相当于 p << cout
	//void operator<<(cout) {
	//
	//}
	int m_a;
	int m_b;
};

//全局函数实现
ostream& operator<<(ostream& cout, Person& p) {
	cout << p.m_a << " " << p.m_b << endl;
	return cout;
}

void test01() {
	Person p;
	cout << p << endl;
}
int main() {
	test01();
	system("pause");
	return 0;
}

递增:

# include <iostream>
# include <string>
using namespace std;

class Person {
public:
	Person() {
		this->m_a = 10;
	}
	//前置++重载
	Person& operator++() {
		m_a++;
		return *this;
	}
	//后置++重载
	Person operator++(int) {
		Person temp = *this;
		m_a++;
		return temp;
	}
	int m_a;
};

//全局函数实现
ostream& operator<<(ostream& cout, Person p) {
	cout << p.m_a << " " << endl;
	return cout;
}

void test01() {
	Person p;
	cout << ++(++p) << endl;
	cout << p << endl;
}

void test02() {
	Person p;
	cout << (p++) << endl;
	cout << p << endl;
}

int main() {
	test01();
	test02();
	system("pause");
	return 0;
}

赋值:

# include <iostream>
# include <string>
using namespace std;

class Person {
public:
	Person(int a) {
		m_a = new int(a);
	}
	~Person() {
		if (m_a != NULL) {
			delete m_a;
			m_a = NULL;
		}
	}
	Person& operator=(Person &p) {
		//先释放堆区的内存 即20
		if (m_a != NULL) {
			delete m_a;
			m_a = NULL;
		}
		m_a = new int(*p.m_a);
		return *this;
	}
	int *m_a;
};

void test01() {
	Person p1(18);
	Person p2(20);
	Person p3(30);
	p3 = p2 = p1;
	cout << *p1.m_a << endl;
	cout << *p2.m_a << endl;
	cout << *p3.m_a << endl;
}

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

关系:

# include <iostream>
# include <string>
using namespace std;

class Person {
public:
	Person(int a, int b) {
		m_a = a;
		m_b = b;
	}
	bool operator==(Person& p) {
		if (this->m_a == p.m_a && this->m_b == p.m_b) {
			return true;
		}
		return false;
	}
	bool operator!=(Person& p) {
		if (this->m_a == p.m_a && this->m_b == p.m_b) {
			return false;
		}
		return true;
	}
	int m_a;
	int m_b;
};

void test01() {
	Person p1(10, 20);
	Person p2(10, 20);
	if (p1 == p2) {
		cout << "p1 == p2" << endl;
	}
	if (p1 != p2) {
		cout << "p1 != p2" << endl;
	}
}

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

函数调用:

# include <iostream>
# include <string>
using namespace std;

class Person {
public:
	Person(int a, int b) {
		m_a = a;
		m_b = b;
	}
	//int operator()(int x, int y) {
	//	return x + y;
	//}
	void operator()(string text) {
		cout << text << endl;
	}
	int m_a;
	int m_b;
};

void test01() {
	//int ans = Person(10, 20)(10, 20);
	//cout << ans << endl;
	Person(10, 20)("hello world");
}

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

继承

继承的目的:减少重复的代码

语法:class 子类 : 继承方式 父类

  • 子类也称为派生类
  • 父类也称为基类
# include <iostream>
# include <string>
using namespace std;

class Base {
public:
	void header() {
		cout << "首页 番剧 直播..." << endl;
	}
	void footer() {
		cout << "国创 时尚 动画..." << endl;
	}
};

class Java : public Base {
public:
	void Tool() {
		cout << "Java视频" << endl;
	}
};

class Python : public Base {
public:
	void Tool() {
		cout << "Python视频" << endl;
	}
};

void test01() {
	Java j;
	j.footer();
	j.Tool();
	Python py;
	py.header();
	py.Tool();
}

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

继承方式:

在这里插入图片描述

# include <iostream>
# include <string>
using namespace std;

class Base {
public:
	int a;
protected:
	int b;
private:
	int c;
};

class Son1 : public Base {
public:
	void change() {
		a = 10;
		b = 20;
		//c = 30;
	}
};

class Son2 : protected Base {
public:
	void change() {
		a = 10;
		b = 20;
		//c = 30;
	}
};

class Son3 : private Base {
public:
	void change() {
		a = 10;
		b = 20;
		//c = 30;
	}
};

class GrandSon3 : private Son3 {
public:
	void change() {
		//a = 10;
		//b = 20;
		//c = 30;
	}
};

void test01() {
	Son1 s1;
	s1.a = 11;
	//s1.b = 21;
	Son2 s2;
	//s2.a = 11;
	//s2.b = 21;
}

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

对象模型:

父类中的所有非静态成员属性都会被子类继承下去

# include <iostream>
# include <string>
using namespace std;

class Base {
public:
	int a;
protected:
	int b;
private:
	int c;
};

class Son1 : public Base {
public:
	int d;
};


void test01() {
	Son1 s1;
	cout << sizeof(s1) << endl;
}

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

继承中构造和析构的顺序:

构造和析构的顺序:先进后出

同名成员处理:

  1. 子类对象可以直接访问子类中的同名成员
  2. 子类对象加作用域可以访问到父类同名成员
  3. 当子类与父类拥有同名的成员函数,子类会隐藏父类中同名成员函数,加作用域可以访问到父类中同名函数
# include <iostream>
# include <string>
using namespace std;

class Base {
public:
	int a = 20;
	void func() {
		cout << "base func()" << endl;
	}
	void func(int m) {
		cout << "base func(" << m << ")" << endl;
	}
protected:
	int b;
private:
	int c;
};

class Son1 : public Base {
public:
	Son1() {
		a = 10;
	}
	int a;
	void func() {
		cout << "Son1 func()" << endl;
	}
};


void test01() {
	Son1 s1;
	cout << s1.a << endl;
	cout << s1.Base::a << endl;
	s1.func();
	s1.Base::func();
	s1.Base::func(2);
}

int main() {
	test01();
	system("pause");
	return 0;
}
# include <iostream>
# include <string>
using namespace std;

class Base {
public:
	static int a;
	static void func() {
		cout << "Base func()" << endl;
	}
	static void func(int m) {
		cout << "Base func(" << m << ")" << endl;
	}
};

int Base::a = 10;

class Son1 : public Base {
public:
	static int a;
	static void func() {
		cout << "Son1 func()" << endl;
	}
};

int Son1::a = 20;

void test01() {
	Son1 s;
	cout << s.a << endl;
	cout << s.Base::a << endl;
	cout << Son1::a << endl;
	cout << Son1::Base::a << endl;
	s.func();
	s.Base::func();
	s.Base::func(3);
	Son1::Base::func();
	Son1::Base::func(3);
}

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

多继承:

语法:class 子类 : 继承方式 父类1 , 继承方式 父类2...

不建议使用

菱形继承:
在这里插入图片描述

# include <iostream>
# include <string>
using namespace std;

class Animal {
public:
	int age;
};

class Sheep : virtual public Animal{};

class Tuo : virtual public Animal{};

class SheepTuo : public Sheep , public Tuo{};

void test01() {
	SheepTuo st;
	st.Sheep::age = 10;
	st.Tuo::age = 9;
	cout << st.Sheep::age << endl;
	cout << st.Tuo::age << endl;
	cout << st.age << endl;
}

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

总结:

  • 菱形继承的问题是子类继承两份相同数据,资源浪费
  • 利用虚继承解决菱形继承问题

多态

基本概念:

多态分为两类:

  • 静态多态:函数重载和运算符重载
  • 动态多态:派生类和虚函数实现

区别:

  • 静态多态的函数地址早绑定 - 编译阶段确定函数地址
  • 动态多态的函数地址晚绑定 - 运行阶段确定函数地址
# include <iostream>
# include <string>
using namespace std;

class Animal {
public:
	virtual void Speak() {
		cout << "动物叫" << endl;
	}
};

class Cat : public Animal {
public:
	void Speak() {
		cout << "小猫叫" << endl;
	}
};

class Dog : public Animal {
public:
	void Speak() {
		cout << "小狗叫" << endl;
	}
};

void doSpeak(Animal& animal) {
	animal.Speak();
}

void test01() {
	Cat c;
	doSpeak(c);
	Dog d;
	doSpeak(d);
}

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

动态多态满足条件:

  • 有继承关系
  • 子类重写父类的虚函数

动态多态使用:父类指针或引用 执行子类对象


原理:

在这里插入图片描述


纯虚函数和抽象类:

纯虚函数语法:virtual 返回值类型 函数名 (参数列表) = 0

当类中有了纯虚函数,这个类也称为抽象类

抽象类特点:

  • 无法实例化对象
  • 子类必须重写抽象类中的纯虚函数,否则也属于抽象类
# include <iostream>
# include <string>
using namespace std;

class MakeDrunk {
public:
	virtual void Boil() = 0 {};
	virtual void Brew() = 0 {};
	virtual void PutInCup() = 0 {};
	virtual void PutSomething() = 0 {};
	void Work() {
		Boil();
		Brew();
		PutInCup();
		PutSomething();
	}
};

class Coffee : public MakeDrunk {
public:
	virtual void Boil() {
		cout << "煮沸农夫山泉" << endl;
	}
	virtual void Brew() {
		cout << "煮咖啡" << endl;
	}
	virtual void PutInCup() {
		cout << "放入杯中" << endl;
	}
	virtual void PutSomething() {
		cout << "放牛奶和糖" << endl;
	}
};

class Tea : public MakeDrunk {
public:
	virtual void Boil() {
		cout << "煮沸自来水" << endl;
	}
	virtual void Brew() {
		cout << "煮茶" << endl;
	}
	virtual void PutInCup() {
		cout << "放入杯中" << endl;
	}
	virtual void PutSomething() {
		cout << "放茶叶" << endl;
	}
};

void doWork(MakeDrunk* md) {
	md->Work();
}

void test01() {
	doWork(new Tea);
	doWork(new Coffee);
}

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

虚析构和纯虚析构:

多态使用时,如果子类中有属性开辟到堆区,那么父类指针在释放时无法调用到子类的析构代码

解决方式:父类中的析构函数改为虚析构和纯虚析构

虚析构和纯虚析构共性:

  • 可以解决父类指针释放子类对象
  • 都需要有具体函数实现

虚析构和纯虚析构区别:

  • 纯虚析构,属于抽象类,无法实例化对象

虚析构:virtual ~类名(){}

纯虚析构:virtual ~类名() = 0 类名::~类名(){}

# include <iostream>
# include <string>
using namespace std;

class Animal {
public:
	Animal() {
		cout << "animal构造" << endl;
	}
	//virtual ~Animal() {
	//	cout << "animal析构" << endl;
	//}
	virtual ~Animal() = 0;
	virtual void Speak() {
		cout << "动物叫" << endl;
	}
};

Animal::~Animal() {
	cout << "animal析构" << endl;
}

class Cat : public Animal {
public:
	Cat(string name) {
		m_Name = new string(name);
		cout << "cat构造" << endl;
	}
	~Cat() {
		if (m_Name != NULL) {
			cout << "cat析构" << endl;
			delete m_Name;
			m_Name == NULL;
		}
	}
	void Speak() {
		cout << "小猫叫" << endl;
	}
	string* m_Name;
};

void test01() {
	Animal* a = new Cat("Tom");
	a->Speak();
	delete a;
}

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

总结:

  1. 虚析构或纯虚析构就是用来解决通过父类指针释放子类对象
  2. 如果子类中没有堆区数据,可以不写虚析构或纯虚析构
  3. 拥有纯虚析构函数的类也属于抽象类

文件操作

对文件进行操作需要包含头文件<fstream>

文件类型:

  1. 文本文件
  2. 二进制文件

操作文件的三大类:

  1. ofstream:写
  2. ifstream:读
  3. fstream:读写

文本文件

写文件:

1.包含头文件

2.创建流对象

3.打开文件

4.写数据

5.关闭文件

打开方式解释
ios::in目的是读文件
ios::out目的是写文件
ios::ate初始位置:文件尾
ios::app追加方式写文件
ios::trunc文件存在先删除,再创建
ios::binary二进制
# include <iostream>
# include <string>
# include <fstream>
using namespace std;

void test01() {
	ofstream os;
	os.open("test.txt", ios::out);
	os << "姓名" << endl;
	os << "性别" << endl;
	os << "年龄" << endl;
	os.close();
}

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

在这里插入图片描述


读文件:

# include <iostream>
# include <string>
# include <fstream>
using namespace std;

void test01() {
	ifstream ifs;
	ifs.open("test.txt", ios::in);
	if (!ifs.is_open()) {
		cout << "error" << endl;
		return;
	}
	//第一种
	//char buf[1024] = { 0 };
	//while (ifs >> buf) {
	//	cout << buf << endl;
	//}
	//第二种
	//char buf[1024] = { 0 };
	//while (ifs.getline(buf, sizeof(buf))) {
	//	cout << buf << endl;
	//}
	//第三种
	//string buf;
	//while (getline(ifs, buf)) {
	//	cout << buf << endl;
	//}
	//第四种
	char c;
	while ((c = ifs.get()) != EOF) {
		cout << c;
	}
	ifs.close();
}

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

二进制文件

打开方式指定:ios::binary

写文件:

调用成员函数write

函数原型:ostream& write(const char * buffer, int len)

解释:buffer->内存中一段存储空间 len是读写的字节数

# include <iostream>
# include <string>
# include <fstream>
using namespace std;

class Person {
public:
	char m_Name[1024];
	int m_Age;
};

void test01() {
	ofstream ofs("person.txt", ios::out | ios::binary);
	Person p = { "张三", 30 };
	ofs.write((const char*)&p, sizeof(p));
	ofs.close();
}

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

在这里插入图片描述


读文件:

调用成员函数read

函数原型:istream& read(char * buffer, int len)

解释:buffer->内存中一段存储空间 len是读写的字节数

# include <iostream>
# include <string>
# include <fstream>
using namespace std;

class Person {
public:
	char m_Name[1024];
	int m_Age;
};

void test01() {
	ifstream ifs("person.txt", ios::in | ios::binary);
	if (!ifs.is_open()) {
		cout << "error" << endl;
		return;
	}
	Person p;
	ifs.read((char*)&p, sizeof(Person));
	cout << p.m_Name << p.m_Age << endl;
	ifs.close();
}

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

(04730)半导体器件之基本放大器工作原理(一) 放大器是构成各种电子线路的基本单元电路。所谓“放大”,就是将输入的微弱信号(微弱变化的电压或电流等)去控制直流电源提供的能量,并使输出按照输入的小信号变化规律而变化的过程。所以放大器的本质是能量转换器。本节重点学习基本放大电路的工作原理和基本分析方法及主要性能指标。 阅读详情

相关推荐

当Kmer遇到多倍体:复杂基因组Survey分析中的避坑指南

本文针对小麦、棉花等多倍体及高杂合复杂基因组的Survey分析,深入解析了Kmer分布图解读中的常见陷阱。文章重点探讨了如何超越理想二倍体模型,利用Smudgeplot等工具准确判断基因组倍性,并提供了从参数优化、污染判断到结果验证的全流程实战指南,帮助研究者规避错误,获得更准确的基因组大小、杂合度等关键信息。

yhn45678901的博客 1008

[笔记]黑马C++核心编程

本阶段主要针对C++==面向对象==编程技术做详细讲解,探讨C++中的核心和精髓。 1 内存分区模型 C++程序在执行时,将内存大方向划分为4个区域 代码区:存放函数体的二进制代码,由操作系统进行管理的 全局区:存放全局变量和静态变量以及常量 栈区:由编译器自动分配释放, 存放函数的参数值,局部变量等 堆区:由程序员分配和释放,若程序员不释放,程序结束时由操作系统回收 内存四区意义: 不同区域存放的数据,赋予不同的生命周期, 给我们更大的灵活编程 1.1 程序运行前 ​ 在程序编译后,生成

jiangqixing0728的博客 487

【scratch音乐课】天空之城:音符与节拍、消息与链表

scratch是一个非常小巧的青少年编程工具,自带程序编写语句,积木式语句非常直观、易用,可创作数学、科学、音乐、绘画等方面作品。本文用scratch“演奏”一首大家非常熟悉的《天空之城》,并向大家介绍一些基本乐理知识,以及scratch中消息、链表的使用。

★·°立芯;︶︵︶ 1万+

C++核心编程(黑马程序员笔记)

C++核心编程 本阶段主要针对C++面向对象编程技术做详细讲解,探讨C++中的核心和精髓。 1 内存分区模型 C++程序在执行时,将内存大方向划分为4个区域 代码区:存放函数体的二进制代码,由操作系统进行管理的 全局区:存放全局变量和静态变量以及常量 栈区:由编译器自动分配释放, 存放函数的参数值,局部变量等 堆区:由程序员分配和释放,若程序员不释放,程序结束时由操作系统回收 内存四区意义: 不同区域存放的数据,赋予不同的生命周期, 给我们更大的灵活编程 1.1 程序运行前 ​ 在程序编译后,生成了ex

念去去 7912

解决uc浏览器劫持video标签问题

解决uc视频悬浮播放 ,video标签被浏览器劫持 ,vide0适配

smile_y_y的博客 3449

将MathType、zotero嵌入Word、WPS

最近也是慢慢学起了写文稿之类的内容,在写论文的时候,肯定会遇到一些数学公式的插入,如果使用wps、word等自带的插入公式,一般不符合投稿期刊的格式要求,而且不方便、不美观,故开始研究MathType 这款插入公式的工具。

2401_83617940的博客 2276

笔记 黑马程序员C++教程从0到1入门编程——核心编程

1 内存分区模型 程序运行前 程序运行运行前,编译后: 84代码区 代码区:存放函数的二进制代码,有操作系统进行管理【共享,只读】 85全局区 全局区:存放全局变量,静态变量(static),常量(字符串常量和const修饰的全局常量(全局常量)) 【在程序结束后由操作系统释放】 //不在全局区的数据:局部变量、const修饰的局部变量(局部常量) 程序运行后 86 栈区 栈区:由编译器自动分配释放,存放函数的参数值,局部变量等 //不要返回局部变量的地址,栈区开辟的数据由..

m0_58125693的博客 5098

AI + 药物临床试验研发赛道

研究日期:2026-07-09 | 研究主题:AI + 药物临床试验研发赛道 | 聚焦岗位:Agent 平台架构师 / AI 工程架构师。

AI天才研究院 146

【C++】黑马程序员-C++核心编程学习笔记

根据黑马程序员C++课程内容,结合讲义,将自己学习C++的过程中将自己觉得有必要记下的笔记进行整理,方便复习回顾,编程环境为VSCode。本阶段主要针对C++面向对象编程技术做详细讲解,探讨C++中的核心和精髓。C++程序在执行时,将内存大方向划分为4个区域内存四区意义:不同区域存放的数据,赋予不同的生命周期, 给我们更大的灵活编程在程序编译后,生成了exe可执行程序,未执行该程序前分为两个区域​ 代码区:​ 存放 CPU 执行的机器指令代码区是共享的,共享的目的是对于频繁被执行的程序,只需要在内存中有一份

qq_62361050的博客 8223

YOLOv8独家原创改进:SPPF原创自研创新 | SPPF创新结构,重新设计全局平均池化层和全局最大池化层,增强全局视角信息和不同尺度大小的特征

SPPF_improve利用全局平均池化层和全局最大池化层,加入一些全局背景信息和边缘信息,从而获取全局视角信息并减轻不同尺度大小所带来的影响

①答疑群聊服务;②YOLO大模型知识问答系统;③计算机视觉论文生成智能体; 4684

【100%通过率】华为od机试C卷【贪吃的猴子】Java&Go 实现

一只贪吃的猴子,来到一个果园,发现许多串香蕉排成一行,每串香蕉上有若干根香蕉。每串香蕉的根数由数组numbers给出。猴子获取香蕉,每次都只能从行的开头或者未尾获取,并且只能获取N次,求猴子最多能获取多少根香蕉。第一次获取香蕉为行的开头,第二次获取为行的末尾,因此最终根数为4+3 =7。全部获取所有的香蕉,因此最终根数为1+2+3 = 6。第二行为数组numbers的值每个数字通过空格分开。1:简单题目,两个指针分别指向头尾,逐个对比即可。第一行为数组numbers的长度。第三行输入为N,表示获取的次数。

MISAYAONE的博客 1436

黑马程序员C++核心编程笔记--2 引用

前三节知识点新版课程已有记录, 详见。

2501_90434822的博客 434

2026年数字IC设计紫光展锐笔试带答案解析

本文是一份数字IC设计工程师/芯片验证工程师的笔试样题,包含单选题和多选题两部分。单选题共20题(每题2分),涵盖数字电路、C++/Verilog编程、芯片设计基础等内容,例如D/A转换计算、面向对象编程特性、三极管工作区域、Verilog仿真时间格式等。多选题15题(每题2分),考察Hold违例修复方法、验证方法学等知识点。试卷总分100分,考试时长90分钟,题型设计兼顾基础理论与工程实践,重点测试应聘者对芯片设计核心概念和工具链的掌握程度。部分题目解析详细说明了计算过程或概念原理,如第1题通过二进制转换

Open 110

08 黑马笔记之C++进阶语法-C++核心编程

月薪过万第一步,先当黑马程序员,本章记录C++语法之C++核心编程易遗忘的点,内容较多,但很细节

qq_54412097的博客 2115

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

黑马程序员C++核心编程笔记--3 函数高级

本节内容之前已经整理过,详见。

2501_90434822的博客 690

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

黑马C++学习笔记——核心编程篇

黑马C++学习笔记——核心编程篇

m0_49687898的博客 2198

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

【C++】黑马程序员C++核心编程学习笔记(完结)

黑马程序员学习笔记——C++核心编程。除上课讲的内容以外还有一些自己的理解。

1万+

黑马程序员匠心之作 || C++核心编程笔记

配套视频:B站:黑马程序员匠心之作|C++教程从0到1入门编程,学习编程不再难(C++核心编程)只是为方便学习,不做其他用途,原作者为黑马程序。函数名可以相同,提高复用性。同一个作用域下函数名称相同函数参数类型不同或者个数不同或者顺序不同函数的返回值不可以作为函数重载的条件。//函数重载需要函数都在同一个作用域下cout

强哥的微博 2279

C++ 黑马程序员-笔记(C++核心编程)

C++ B站黑马程序员 目录C++核心编程内存分区模型程序运行前程序运行后new 操作符引用引用的基本使用引用注意事项引用做函数参数引用做函数返回值引用的本质常量引用函数提高函数默认参数函数占位参数函数重载类和对象封装封装意义一封装意义二(访问权限)struct 和 class 区别成员属性设置为私有练习案例1:设计立方体类练习案例2:点和圆的关系对象的初始化和清理构造函数和析构函数构造函数的分类及调用💖拷贝构造函数调用时机构造函数调用规则深拷贝与浅拷贝初始化列表类对象作为类成员静态成员cpp对象模型和 t

m0_49734843的博客 1670

C++核心编程-黑马笔记(自用)

C++核心编程,冲冲冲

Dijkstraand的博客 1564

《黑马笔记》 --- C++核心编程

本文介绍了C++中的内存管理模型和引用机制。主要内容包括: 内存分区模型 代码区:存放代码,由OS管理 全局区:存放全局变量、静态变量和常量 栈区:存放局部变量,由编译器管理 堆区:程序员手动管理的内存,使用new/delete操作 引用机制 引用是变量的别名,本质是指针常量 引用必须初始化且不可更改 引用可作为函数参数和返回值,提高代码可读性 注意不要返回局部变量的引用 函数相关 默认参数的使用规则 函数重载的条件:同一作用域、同名、参数不同 这些内容是C++编程中内存管理和参数传递的重要基础。

layfolk的博客 580

黑马C++笔记 核心编程篇(1)

主要针对C++的“面向对象”编程技术做详细讲解。

2403_89908394的博客 1008

黑马程序员C++核心编程笔记--4 类和对象--多态

多态是C++面向对象三大特性之一多态分为两类静态多态和动态多态区别:-静态多态的函数地址早绑定 - 编译阶段确定函数地址-动态多态的函数地址晚绑定 - 运行阶段确定函数地址下面通过案例进行讲解多态总结:多态满足条件有继承关系子类重写父类中的虚函数多态使用条件父类指针或引用指向子类对象重写:函数返回值类型 函数名 参数列表 完全一致称为重写。

2501_90434822的博客 766

黑马程序员c++学习笔记----c++核心编程

c++核心编程 本阶段主要针对cpp面向对象编程技术做详细讲解,探讨cpp中的核心和精髓。 1 内存分区模型 cpp程序在执行时,将内存大方向划分为4个区域 代码区:存放函数体的二进制代码,由操作系统进行管理的 全局区:存放全局变量和静态变量以及常量 栈区:由编译器自动分配释放, 存放函数的参数值,局部变量等 堆区:由程序员分配和释放,若程序员不释放,程序结束时由操作系统回收 内存四区意义: 不同区域存放的数据,赋予不同的生命周期, 给我们更大的灵活编程 1.1 程序运行前 ​ 在程序编译后,生成了ex

qq_36421001的博客 8011

【C++】黑马程序员 | c++教程从0到1入门编程笔记 | c++核心编程

1

qq_38939822的博客 1614

B站黑马c++学习笔记 —— 核心编程篇

大纲1 内存分区模型1.1 程序运行前1.2 程序运行后1.3 new操作符2 引用3 函数提高4 类和对象5 文件操作 1 内存分区模型 1.1 程序运行前 1.2 程序运行后 1.3 new操作符 2 引用 3 函数提高 4 类和对象 5 文件操作 ...

qq_52382976的博客 2706
上一篇: 【二分查找】LC习题看这一篇就够了!
下一篇: C++提高编程(黑马笔记)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值