C++基础速通

其它的和C相差无几,参照b站cpp课程-哔哩编程学院,菜鸟cpp教程,

【Visual Studio 2022】常用快捷键和一些小技巧。

1. cpp 基本输入输出

#include   
using namespace std;
class A {
public: 
    
};
class A1 :public A {
    
};
int main()
{
   
	return 0;
}

1.1 cout详解

cout ;
cout << "Hello World" ;//直接字符串
cout << name ; //字符串地址
<< endl ://换行

1.2 不一样的数据类型

cpp中 int x{ }int x = 0是一回事么?。

int a{10}; //int a=10; 效果一样
int b{ };// int b{0}; int b=0;

1.3 见多识广

return; return 0; return -1; return 1之间的区别。

void test01()
{
	ifstream ifs;
	ifs.open("test.txt", ios::in);
	if (!ifs.is_open())
	{
		cout << "文件打开失败" << endl;
		return; //void函数返回,退出整个程序。
	}
}

2. 接轨C语言

1. bool类型

相比 int 的0,1更节约内存。非0即1,方便判断

#include   
using namespace std; 
int main()
{
	bool a = true; //ture就是1
	a = false; //false就是0
	a = 123;  //非0即1
	a = 3.14;
	cout << a << endl << sizeof(bool);  //长度都是1个字节。
	return 0;
}

2. 内联函数

一般用于简单函数,占用内存不大的。

就函数声明、函数定义前加上关键字:inline

#include   
using namespace std;

inline void func(int num);  //声明
int main()
{
	func(4);
	return 0;
}
inline inline void func(int num) {  //定义
	cout << num ;
}

3. 函数重载

同一项目,函数名字可以重复。

但函数的参数列表必须不同:不同个数,同个数对应位置类型不同。

只有返回值不同不行!

4. 函数参数缺省

声明函数某个参数时,指定一个默认值,调用时缺省则默认。

从右到左排!

#include   
using namespace std; 
void func(int num, float val = 2, double db = 3);//声明处默认
int main()
{
	func(4); //调用时 参数缺省
	return 0;
}
void func(int num, float val, double db) {
	cout << num <<endl << val <<endl << db;
}

5. 引用

5.1 变量、对象取别名

指向同一地址,心连心,1变则2变,定义引用的时候必须初始化。

#include   
using namespace std;
class Person {
public:
	int age;
	string name;
};
int main()
{
	int a1 = 0;
	int a2 = 3;
	int& b1 = a1;  //int* const b1 = &a1; 使用时直接用b1,用*b1会报错!
	int& b2 = a2;  //引用变量,必须同时初始化
	cout << b1 << endl; //0
	cout << b2 << endl; //3
	b1++; //心连心
	cout << a1 << endl; //1
	b1 = a2;  //赋值!不能更改引用。
	cout << a1 << endl; //3
	b1 = b2;  //同 b1 = a2,赋值,不能更改引用
	b1++;
	cout << a1 << endl; //4
	cout << a2 << endl; //3

	Person Tom;
	Person& Tomc = Tom;
	Tomc.age = 2;
	cout << Tom.age; //2
	return 0;
}
5.2 引用函数传参
#include
using namespace std;
//1. 值传递
void mySwap01(int a, int b) {
	int temp = a;
	a = b;
	b = temp;
}
//2. 地址传递
void mySwap02(int* a, int* b) {
	int temp = *a;
	*a = *b;
	*b = temp;
}
//3. 加个引用,让形参能够改变实参!
void mySwap03(int& a, int& b) {
	int temp = a;
	a = b;
	b = temp;
}
int main() {
	int a = 10;
	int b = 20;
	mySwap01(a, b);  //10,20  不能交换
	cout << "a:" << a << " b:" << b << endl;
	mySwap02(&a, &b);//20,10  指针肯定可以交换
	cout << "a:" << a << " b:" << b << endl;
	mySwap03(a, b);  //10,20  引用也能交换!比指针简洁。
	cout << "a:" << a << " b:" << b << endl;
	return 0;
}
5.3 引用作函数返回值
#include
using namespace std;
//返回局部变量引用
int& test01() {
	int a = 10; //局部变量
	return a;
}
//返回静态变量引用
int& test02() {
	static int a = 20; //静态变量,相当于全局变量!
	return a;
}
int main() {
	//不能返回局部变量的引用
	int& ref = test01(); //局部变量,函数执行完就释放内存了!
	cout << "ref = " << ref << endl; 
	cout << "ref = " << ref << endl; 
	//如果函数做左值,那么必须返回引用
	int& ref2 = test02();   //别名,左右一样
	cout << "ref2 = " << ref2 << endl;
	cout << "ref2 = " << ref2 << endl;
	test02() = 1000;  //左值
	cout << "ref2 = " << ref2 << endl;
	cout << "ref2 = " << ref2 << endl;
	return 0;
}
5.4 引用作函数重载
#include   
using namespace std;
//1、引用作为重载条件
void func(int& a) //int& a = 10;非法
{
	cout << "func (int &a) 调用 " << endl;
}
void func(const int& a)// const int& a = 10;合法,编译器:int noname = 10;int& a = noname;
{
	cout << "func (const int &a) 调用 " << endl;
}
int main() {
	int a = 10;
	func(a); //调用无const
	func(10);//调用有const
	return 0;
}

6. 命名空间

命名空间 ::(的)元素

#include   
using namespace std; //引入整个空间,内存较大?
// using std::cout;
// using std::endl;
namespace NAME_1 {
	namespace NAME_1_1 { // 嵌套
		int num = 8;
	}
	int num=9;
	float cal;
	void func_1() {
		cout << "func1" << endl;
	}
	void func_2();
}
namespace N = NAME_1;//取别名

void NAME_1::func_2() { //定义命名空间的
	cout << "func_2" << endl;
}
int main()
{
	int num = 10;
	cout << "main"<<endl;
	NAME_1::func_1();
	NAME_1::func_2();
	cout << num<<endl; //10
	cout << NAME_1::num << endl;//9
	cout << NAME_1::NAME_1_1::num << endl;//8
	return 0;
}

7. New和Delete

直接new一个指针,省去变量名。

申请和释放内存。

#include   
using namespace std;
int main()
{
	//申请单个内存
	int* p1 = new int;
	cout << p1 << endl;
	cout << &p1 << endl;
	*p1 = 0;
	cout << *p1 << endl;

	//申请单个内存且初始化
	int* p2 = new int(666);
	cout << *p2 << endl;

	//批量申请(连续的内存),不能再给初值。
	int* p3 = new int[10];

	//释放内存
	delete p1; //只有new出来的指针才能delete,否则运行出错!
	delete p2;
	delete p3;//只能释放一个
	delete[] p3;//释放连续的一段,只能向后,必须首地址!
	return 0;
}

3 . 类与对象

3.1. 类 > 对象 . 元素,

类 :: 方法。

类修饰词:private,public,protected

#include   
#include
#include
using namespace std;
//全局区域
class Sheep {
	int age=0; //默认私有,只能在类里面调用
public:
	char name[32]; //只能里面直接赋值,外面只能strcpy; 有string类,谁还用c的字符串?
    string name2; //cpp特有强大的字符串!
	void speak();
	void setAge(int n) { // 可以设置,不可以直接访问age
		age = n;
	}
	int getAge() {
		return age;
	}
private: 
	int birthday;
	void eat() {
		cout << "吃" << endl;
	}
protected: //继承的而已可以访问
};
void Sheep::speak() { // 类(的)::
	cout << "咩" << endl;
}
int main()
{
	Sheep xi;
	// xi.name = "喜羊羊"; 错误。但类里 string name;外面就可以直接赋值了。
	// xi.name[] = "喜羊羊"; 错误
	strcpy_s(xi.name,"喜羊羊"); //出来后只能用 strcpy 赋值就离谱。
	cout << xi.name << endl ;
	xi.speak(); //咩
	xi.setAge(12);
	cout << xi.getAge() << endl;
	//对象指针!!!
	Sheep* pxi = &xi; 
	pxi->speak(); //指针肯定指->,对象才用点.
	return 0;
}

3.2. string类

小写的string !

#include   
// #include c语言的,多个.h
#include
using namespace std;

int main()
{
	string str; //相比c,更强大的字符串类型!附带字符串处理函数!
	str = "abc123"; //赋值
	char ch;
	ch = str[0]; // 取特点值
	cout << ch << endl;
	ch = str.at(1); 
	cout << ch << endl;
	cout << str.length()<<endl; //长度
	str = "abc12314131313321312312312312312"; //动态长度?随意赋值?
	cout << str.length()<<endl;
	str.clear();//清空
	if (str.empty()) { //判空
		cout << "非空" << endl;
	}
	else {
		cout << "空" << endl;
	}
	string str2 = "串2";
	if (str == str2) {//直接等号比较!!!
		cout << "同" << endl;
	}
	else {
		cout << "不同" << endl;
	}
	return 0;
}

3.3 构造函数

cpp 类构造函数 & 析构函数,

类的构造函数:创造对象时自动执行!用来赋值基本属性等很好用

#include   
using namespace std;
class Sheep {
public:
	int age;
	int size;
	Sheep() { //必须与类名一样,无返回值,无返回类型,
		cout << "默认无参,不写也有的构造函数" << endl;
	}//但是,自己写了有参的,默认无参的不写就没了,构造对象时就不能不带参了。
	Sheep(int, int any = 0); //也可以初始值,声明变量名也定义的形参名可以不一样!
};
Sheep::Sheep(int age, int size) { //里外定义都可以
	cout << "自定义带参构造函数" << endl;
	this->age = age;
	this->size = size;
}
int main()
{
	Sheep xi;
	Sheep lan(10, 100); //构造函数就这而已
	cout << lan.age << "  " << lan.size << endl;
    //同理对象指针,直接new省去对象名
	Sheep* pmei = new Sheep;
	Sheep* pfei = new Sheep(14);//默认0
	cout << pfei->age << "  " << pfei->size << endl;
	return 0;
}

3.4. 析构函数

创造对象时自动调用 构造,对象生命结束时自动调用 析构。

但人为调用时,对象没有结束。

对象指针形式的,不会自动调用,必须手动释放内存。

Sheep* pmei = new Sheep;
delete pmei;//只能手动释放内存,才会调用析构函数,释放之后就不能用这个对象(指针)了。

必须public。

~Line();  // 这是析构函数声明

3.5.拷贝构造

复制对象。

也是类中默认有的

Sheep(const Sheep& obj){}; //默认完全1:1复制,
Sheep(const Sheep& obj,int n){};//复制的基础上,添加属性
Sheep(int a,const Sheep& obj,int n){};//不是拷贝构造了,第一个参数必须对象的引用。
Sheep lan2= lan;
cout << lan2.age << "  " << lan2.size << endl;
Sheep lan3(lan); //一样的完全复制
cout << lan3.age << "  " << lan3.size << endl;

3.6.关键字this,static,const

谁没事会用这些嘛,看得懂就行

this :形参名和类中变量名相同是使用

类中const修饰变量初始化,一旦初始化,方法,对象中都不能修改

static:静态变量,存在类里,类的所有对象共用。

static int num;

Sheep xi;
Sheep lan; //同一个类的对象
xi.num =0; //可以用于创造的对象个数计数。
lan.num=1;//同一个num,一改都改
Sheep::num;//也可以类名直接访问。

静态方法。

static void func();//类中,声明加static

void Sheep::func(){//类外,定义不用加了
    //不同访问类中普通成员(包括变量和方法)!不能用this。
    //只能访问静态成员
}
Sheep xi;
xi.func();//对象调用
Sheep::func(); //直接类调用,

const:类中,常量数据,常量函数

const int val; //成员初始化列表赋值	,否则不能改
static int num;
void func() const{ //后面 加个const
    cout<<"func1"<<endl;
    //val = 0;等等错误,能访问,但都不能改成员!就保险一点而已。
    num = 0;// 但静态成员可以改
}

3.7. 对象的初始化

3.7.1 构造函数…

3.7.2 初始化列表

赋值操作都可用列表的形式给出

省了this->age = age; this->size = size; 不用this了,自动识别。

#include   
using namespace std;
class A {
    int a1;  //private
public:
    char* str;
    int age;
    A(int a1, char* str, int age) :a1(a1), str(str), age(age) {
        cout << "A的初始化列表构造"<<endl;
    };
    void f() {
        cout << a1 <<endl << age << endl;
        cout << str;
    }
};
int main()
{
    char s[10] = "123";
    A a(1, s, 2);
    a.f();
    return 0;
}

3.7.3 用{ }初始化

无需构造函数。

全public可以用{ }直接初始化,有private,protected就不行。

#include   
using namespace std;
class A {
public:
    char str[100];
    int age;
    int a2;
    void f() {
        cout << age;
    }
};
int main()
{
    A a = { "123",1 };// c11 { }用于初始化对象
    a.f();
    return 0;
}

4. 继承

4.1 继承方式

无论怎样,都不能继承父类的私有private属性8

public:一般都public继承,父类public,protected不变

protecte:全变protected

private:全变private

废话:父类中私有成员也是被子类继承下去了,只是由编译器给隐藏后访问不到。

4.2 继承同名成员处理方式

Son s;
s.func(); //子类对象
s.Base::func();//子类对象.父类Base::的函数
s.Base::func(10); //重载

加上:静态可用类名访问

Son::func();
Son::Base::func(); //子类::父类::static函数
Son::Base::func(100);

4.3 多继承

cpp实际开发中不建议用多继承,看见了认识就行。

class Son : public Base2, public Base1 
{
}

5. 多态

5.1 函数重载 和 运算符重载

函数重载:同名不同形参…

5.2 函数重写

同名同参。函数返回值类型 函数名 参数列表 完全一致。

#include   
using namespace std;
class A
{
public:
	int Func() { //多态1:函数重写,子父类同名函数。
		cout << "父A" << endl;
		return 0;
	}
};
class A1 :public A {
public:
	int Func() {
		cout << "子A1"<<endl;  //相同函数,不同子类,不同实现 => 多态
		return 1;
	}
};
class A2 :public A {
public:
	int Func() {
		cout << "子A2" << endl;  
		return 2;
	}
};
int main()
{
	A a;  //父类可以实例化对象
	A1 a1;
	A2 a2;
	cout << a.Func() << endl; //父A 0
	cout << a1.A::Func() << endl; //父A 0,子类对象可以调用父类的函数
	cout << a1.Func() << endl;//子A1 1
	cout << a2.Func() << endl;//子A2 2
	cout << a2.A::Func() << endl; //父A 0
	return 0;
}

5.3 父类形参

父类指针或引用指向子类对象。

继承父类virtual虚函数,子类实现,百花齐放。

父类的函数必须vitrual,否则传入子类对象也只能调用父类函数!!

void testFunc1(A& a) { ...... }
testFunc1(a1); //A& a = a1;多态:父类引用 = 子类对象;
testFunc2(&a1);//A* a = &a1;多态:父类指针 = 子类对象地址;

A* pa = new A1;//new指针父类形参
A& pa2 = *(new A2); //*new引用父类形参
delete pa;//父类指针释放子类对象,会释放不干净,需要实现虚析构函数进一步释放。
#include   
using namespace std;
class A
{
public:
	virtual int Func() { //函数重写:子父类同名同参函数。
		cout << "父A" << endl;
		return 0;
	}
};
class A1 :public A {
public:
	int Func() {
		cout << "子A1" << endl;  //相同函数,不同子类,不同实现 => 多态
		return 1;
	}
};
class A2 :public A {
public:
	int Func() { //父类同名的函数可以不virtual,函数重写而已。
		cout << "子A2" << endl;
		return 2;
	}
};
void testFunc1(A& a) { //A& a = a1;
	a.Func();  //父类形参,父类的函数必须vitrual,否则传入子类对象也只能调用父类函数!!
}
void testFunc2(A* a) { //A* a = &a1;
	a->Func();
}
int main()
{
	A a;  //父类可以实例化对象
	A1 a1;
	A2 a2;
	cout << a.Func() << endl; //父A 0
	cout << a1.A::Func() << endl; //父A 0,子类对象可以调用父类的函数
	cout << a2.A::Func() << endl; //父A 0
	cout << a1.Func() << endl;//子A1 1
	cout << a2.Func() << endl;//子A2 2
	cout << "=========================="<<endl;
	//A a = new A1; 不能直接父类形参
	A* pa = new A1;   
	pa->Func(); //子A1,new指针父类形参
	A& pa2 = *(new A2);
	pa2.Func(); //子A2,*new引用父类形参
	cout << "==========================" << endl;
	testFunc1(a); // A& a = a;引用别名自己
	testFunc1(a1); //A& a = a1;多态:父类引用 = 子类对象;
	testFunc1(a2);

	testFunc2(&a);
	testFunc2(&a1);//A* a = &a1;多态:父类指针 = 子类对象地址;
	testFunc2(&a2);
	return 0;
}

5.4 纯虚函数<->抽象类

类似java的接口…

类中只要有一个纯虚函数就称为抽象类:

  • 无法实例化对象:不能A a;,也不能new:A* pa1 = new A1;
  • 子类必须重写抽象类中的纯虚函数,否则也属于抽象类
#include   
using namespace std;
class A {
	virtual int Func() = 0;  //纯虚函数
};
class A1 :public A {

};
class A2 :public A {
public:
	int Func() {
		cout << "A2" << endl;
		return 1;
	}
};
int main()
{
	//A1 a; 抽象类不允许实例化对象,子类没重写,也为抽象类。
	A2 a2;
	cout<<a2.Func(); //先执行函数,再输出返回值。
	//A* pa1 = new A1; 不能new 抽象类!
	//A1* pa1 = new A1;
	return 0;
}

5.5 虚析构 / 纯虚析构

一般用不上,看到认识就行。

虚析构和纯虚析构共性:

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

虚析构和纯虚析构区别:

  • 如果是纯虚析构,该类属于抽象类,无法实例化对象
virtual ~Animal() = 0; //1. 父类虚析构
~Cat()
	{
		cout << "Cat析构函数调用!" << endl;
		if (this->m_Name != NULL) {
			delete m_Name; //2. 子类析构释放进一步内存
			m_Name = NULL;
		}
	}

6. 文件:开,干,关

写:一次,不用循环

读:每次指定大小读入,每次大小可能不一样,多次就用while循环,直到结束file.read()返回假!

C语言中文网cpp文件,挺详细的

操作文件的三大类:

  1. ofstream:写操作
  2. ifstream: 读操作
  3. fstream : 读写操作,一般都用这个,前俩看见认识就行。

文件打开方式:

打开方式 解释
ios::in 为读文件而打开文件
ios::out 为写文件而打开文件
ios::ate 初始位置:文件尾
ios::app 追加方式写文件
ios::trunc 如果文件存在先删除,再创建
ios::binary 二进制方式

注意: 文件打开方式可以配合使用,利用|操作符

**例如:**用二进制方式写文件 ios::binary | ios:: out

6.1 写 file <<

写到一个txt文件中,没有自动创建

#include
#include  //file stream
using namespace std;
int main() {
	//写到一个txt文件中,out方式打开,没有就自动创建,重名是直接覆盖!
	fstream file;
	file.open("test.txt", ios::out);
	file << "姓名:李四" << endl << "性别:男" << endl << "年龄:18" << endl;
	file.close();
	return 0;
}

6.2 读

6.2.1 file >> buf

读一个txt文件,一行一行字符串

#include
#include  //file stream
#include
using namespace std;
int main() {
	char ch = 97; //数字会ascll转换
	cout << ch << endl; //a
	char arr[3] = "12";
	cout << arr << endl; //12,字符串首地址就会输出真个字符串!
	//写到一个txt文件中,in方式打开,需要判断是否打开成功!
	fstream file;
	file.open("test.txt", ios::in);
	if (file.is_open())
	{
		cout << "文件打开成功" << endl;
	}
	else {
		return -1;//非0,不正常退出
	}
	char buf[1024] = { 0 }; //最大1024字节,字符串缓冲区
	cout << sizeof(buf) << endl; //1024
	while (file >> buf) //一行一行读到buf
	{
		cout << buf << endl; //打印buf整个字符串。
	}
	file.close();
	return 0;//0,执行完毕,正常退出
}

6.2.2 file.getline( )

istream& getline (char* s, streamsize n );
istream& getline (char* s, streamsize n, char delim );

从istream中读取至多n个字符(包含结束标记符)保存在s对应的数组中。即使还没读够n个字符。如果遇到delim(默认为’\0’) 或 字数达到限制,则读取终止,delim都不会被保存进s对应的数组中。

#include
#include 
using namespace std;
int main() {
	fstream file;
	file.open("test.txt", ios::in);
	if (file.is_open())
	{
		cout << "文件打开成功" << endl;
	}
	else {
		return -1;//非0,不正常退出
	}
	char buf[1024] = { 0 }; // sizeof(buf)为1024
	while (file.getline(buf,sizeof(buf)))
	{
		cout << buf << endl;
	}
	file.close();
	return 0;//0,执行完毕,正常退出
}

6.2.3 getline()

#include中的 getline( )函数

istream& getline (istream&  is, string& str, char delim);
istream& getline (istream&& is, string& str, char delim);
istream& getline (istream&  is, string& str);
istream& getline (istream&& is, string& str);
用法和上第一种类似,但是读取的istream是作为参数is传进函数的。读取的字符串保存在string类型的str中。
#include
#include 
#include //包含string
using namespace std;
int main() {
	fstream file;
	file.open("test.txt", ios::in);
	if (file.is_open())
	{
		cout << "文件打开成功" << endl;
	}
	else {
		return -1;//非0,不正常退出
	}
	//第三种
	string sf;
	while (getline(file, sf))
	{
		cout << sf << endl;
	}
	file.close();
	return 0;//0,执行完毕,正常退出
}

6.2.4 file.get()

一个字符一个字符读,牛!

#include
#include 
using namespace std;
int main() {
	fstream file;
	file.open("test.txt", ios::in);
	if (file.is_open())
	{
		cout << "文件打开成功" << endl;
	}
	else {
		return -1;//非0,不正常退出
	}
	//第4种
	char c;
	while ((c = file.get()) != EOF)
	{
		cout << c;
	}
	file.close();
	return 0;//0,执行完毕,正常退出
}

可以发现,无论怎样,都得先对象后open,可以使用构造器,一步到位。

fstream file("person.txt", ios::out | ios::binary);

6.3 bf.write()

cpp二进制读写详细用法。

binary file,bfile,bf。

二进制.读写,一个字节一个字节的读写!(char,8 bit = 1byte)

对象,变量,数组…二进制底层原样保存到文件,原样读出!

一个对象的write(),二进制格式写入文件。

#include   
#include
using namespace std;
class A {
public:
    int a1;
    //char* str; 这样只会保存地址,不会保存数据,下次启动内存释放了,不能用地址得到数据!
    char str[100];
};
int main()
{
    A a1 = { 1,"你" };//大括号直接赋值初始化!无需构造函数
    A a2 = { 2,"你好" };
    A a3 = { 3,"你好中国" };
    //把对象写入文件
    fstream bf("binary.txt", ios::out | ios::binary); //out不用关心文件异常,合并省略open()
    bf.write((char*)&a1, sizeof(a1)); //write 二进制
    bf.write((char*)&a2, sizeof(a2)); //write 二进制
    bf.write((char*)&a3, sizeof(a3)); //write 二进制
    bf.close();
    return 0;
}

6.4 bf.read()

读取一个二进制文件,

每次读到哪里,读多少;读完了返回假。

#include   
#include
using namespace std;
class A {
public:
    int a1;
    char str[100];
};
int main()
{
    fstream bf;
    bf.open("binary.txt", ios::in | ios::binary);
    if (!bf.is_open()) { //读取,必须open并判断
        cout << "failure to open file";
        return -1;
    }
    //怎么写的就怎么读!定义对象读出来就是!
    A* pa = new A();
    while (bf.read((char*)pa, sizeof(*pa))) {
        cout << pa->a1 << endl << pa->str;
    };
    bf.close();
    return 0;
}

你可能感兴趣的:(c/c++,c++,开发语言)