c++学习笔记

c++学习笔记

注:我是看视频敲的代码 视频学习链接 侵删
黑马程序员匠心之作|C++教程从0到1入门编程,学习编程不再难

1、基本使用
#include<iostream>
#include <string>
using namespace std;
int *swap(int *a, int *b) {
	int ARR[2];
	int tem = *a;
	*a = *b;
	*b = tem;
	ARR[0] = *a;
	ARR[1] = *b;
	return ARR;
}
void swap2(int &c,int &d) {
	int tem = c;
	c = d;
	d = tem;


}
// 结构体
struct MyStruct
{
	int age;
	string name;
};

//结构体指针--嵌套结构体
struct MyStruct2
{
	int age;
	string name;
	MyStruct s;
};
//引用 int &小名=原名

int main() {
	int arr[3] = { 2,3,4 };
	int a = 3;
	int b = 4;
	int *rr;
	MyStruct s3[3];
	MyStruct2* s4=new MyStruct2[2];
	MyStruct2 *ssss = new MyStruct2[12];
	s4->age = 13;
	s3[0].age = 16;
	s3[0].name = "计算机";
	cout << s3[0].age << "姓名" <<s4->age<< s3[0].name << endl;
	swap2(a, b);
	cout << a << "-------" << b<< endl;
	delete []s4;// 对应New 使用的数组  学习到引用的注意事项
	//引用之前必须初始化,引用一旦初始化之后 就不可以更改引用
	// 静态变量存放在全局区 static int s;存放的是全局区
}
2、引用的本质
  • 引用的本质是指针常量

  • *相当于解引用,找到变量的地址

#include<iostream>
#include <string>
using namespace std;
void swap(const int &a){
    a=1000;//将会报错,因为有const修饰
}
3、函数的提高
3.1 函数的默认参数
#include<iostream>
#include <string>
using namespace std;

int fun(int a,int b=10 ,int c=10) {
	
	return a + b + c;

}

int main() {
	cout << fun(10, 20, 30);//c传入参数就用传入的参数 否则就用默认的参数
	// 从某个位置有了默认参数,则从左到右必须都要有
    // 函数实现和声明只能一个有默认参数
}
3.1 函数的占位参数
#include<iostream>
#include <string>
using namespace std;
int fun(int a ,int) {//第二个参数就是占位符亦可以默认参数  int a=10
	return a ;
}

int main() {
	cout << fun(10, 20);//c传入参数就用传入的参数 否则就用默认的参数
	// 从某个位置有了默认参数,则从左到右必须都要有
}
3.2函数的重载

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

满足条件:

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

注意:函数的参数不可以作为函数重载的条件

#include<iostream>
#include <string>
using namespace std;
// 函数重载
void fun() {
	cout << "函数重载fun()" << endl;
}
void fun(int a ) {// 函数参数个数不同
	cout << "函数重载fun(int a)" << endl;
}
void fun(double a) {// 函数参数类型不同
	cout << "函数重载fun(double a)" << endl;
}
void fun(double a,int b) {// 函数参数类型不同
	cout << "函数重载fun(double a,int b)" << endl;
}
void fun(int a, double b) {// 函数参数顺序不同
	cout << "函数重载fun(int b,double a)" << endl;
}
void fun(const int &a) {// 函数参数顺序不同
	cout << "函数重载fun(const int b,double a)" << endl;
}
void fun(int &a ) {// 函数参数个数不同
	cout << "函数重载fun(int a)" << endl;
}
//int fun() { 
//	cout << "函数返回值不可以重载fun()" << endl;
//}

int main() {
    fun(a);//调用无const
	fun(10);// 调用有const
	fun();
	fun(10);
	fun(10, 0.1);
	return 0;
}
// 函数重载遇到默认参数时就会报错 尽量避免这种情况
4.类和对象
#include<iostream>
#include <string>
using namespace std;
#define PI 3.14;


// 类和对象
class student
{
public:
	//属性 成员属性 成员变量
	string name;
	string num;
	void setName(string nnname) {
		name = nnname;
	}
	// 行为-方法
	void getData() {
		cout << name << "----" << num << endl;
	}
};


int main() {
	//实例化对象
	student s;
	//s.name = "张三";
	s.setName("张三");
	s.num = "123321";
	s.getData();
	return 0;
}
4.1访问权限
#include<iostream>
#include <string>
using namespace std;
#define PI 3.14;


// 访问权限
class student
{
public://类内部可以访问 类外可以访问
	string name;
	void setname(string outcar) {
		car = outcar;
		cout << "可以访问" << endl;
		show(outcar);
	}
protected://类内部可以访问 类外不可以访问
	string car;
	void show(string ccc) {
		cout << ccc<< endl;
	}
private://类内部可以访问 类外不可以访问
	int password;
};


int main() {
	student s;
	s.setname("宝马");
	//s.show();//报错 外部不可以访问
	return 0;
}

4.2 struct 和 class的区别
  • struct 默认权限 public

  • class 默认权限 private

4.3成员属性私有化
#include<iostream>
#include <string>
using namespace std;
#define PI 3.14;


// 成员属性设置为私有 
// 可以自己控制读写权限
// 对于写可以检测数据的有效性
// 写  -----set方法  读----get方法
class person
{
public:
	void setName(string nname) {//写
		name = nname;//传入参数和成员变量名称尽量不一样
	}
	void getName() {//读
		cout << "姓名:" << name << endl;
	}
	void getAge() {//读
		age = 0;
		cout << "年纪:" << age << endl;
	}
private:
	string name;//可读可写
	int age;//可读
	string lover;//可写

};


int main() {
	person p;
	p.setName("xzs");
	p.getName();
	p.getAge();
	//p.setAge();//年纪不可写 报错
	return 0;
}

4.4对象的初始化和清理
  • 构造函数:初始化 --主要用于创建对象时为对象成员赋值,由编译器自动调用 无需手动调用
  • 析构函数:清理-对象销毁前系统自动调用,执行一些清理工作。
  • 以上函数由编辑器自动调用,如果不写 编译器提供的是二者的空实现
#include<iostream>
#include <string>
using namespace std;

class MyClass
{
public:
	MyClass(int a) {
		age = a;
		cout << "构造函数" << endl;
	}
	~MyClass() {
		cout << "析构函数" <<age<< endl;
	}
	void setAge(int agge);
private:
	int age;
};


void test(int a) {
	MyClass c(10);

}
int main() {
	test(10);
	return 0;
}

4.5构造函数的分类以及调用
  • 构造函数的分类

    • 1.参数类型
      • 无参构造函数
      • 有参构造函数
      • 2.构造类型
        • 普通构造函数

        • 拷贝构造函数

  • 函数调用

    • 采用括号调用 显示调用即可
#include<iostream>
#include <string>
using namespace std;

class person
{
public:
	person(int aage) {
		cout << "有参构造" << endl;
	}
	person() {
		cout << "无参构造函数" << endl;
	}
	person(const person& p) {
		cout << "拷贝构造函数" << endl;
	}

public:
	int age;
};



int main() {
	// 调用
	person p;// 不可以写成person p();
	person p2(10);
	person p3(p2);
	return 0;
}

4.3拷贝构造函数调用时机
  • 使用一个已经创建完毕的对象初始化一个新对象
  • 值传递的方式给函数参数传值
  • 以值方式返回局部对象
4.4g构造函数调用规则

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

  • 默认构造函数(无参,函数体为空)
  • 默认析构函数(无参,函数体为空)
  • 默认拷贝构造函数,对属性进行值拷贝

给猴枣函数调用规则如下:

  • 如果用户定义有参构造函数,c++ 不提供默认无参构造函数,但是提供默认拷贝构造
  • 如果用户定义拷贝构造函数,c++不会再提供其他构造函数
4.5 深拷贝与浅拷贝
  • 深拷贝: 在堆区重新申请空间进行拷贝操作
  • 浅拷贝:简单的赋值拷贝操作

​ new 关键字开辟的是堆区 需要手动释放 析构函数不能进行释放

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

class person
{
public:
	person(int a,int eight ) {
		age = a;
		height = new int(eight);
		cout << "构造函数" << endl;
	}
	~person() {
		// 浅拷贝带来的问题就是堆区内存的重复释放 需要利用深拷贝解决
		if (height!=NULL)
		{
			delete height;
			height = NULL;
		}
		cout << "p析构函数" << endl;
	}
	person(const person& p) {
		age = p.age;
		//height = p.height;//这是编译器自己默认实现的,需要自己进行深拷贝操作
		height = new int(*p.height);//堆上面申请的空间
		cout << "拷贝构造函数" << endl;
	}

public:
	int age;
	int* height;//指针类型  
};

void test() {
	person p(10,90);
	cout << "p的年龄" << p.age << endl;
	person p2(p);
	cout << "p2的年龄" << p2.age << endl;
}

int main() {
	test();
	return 0;
}

浅拷贝带来的问题就是堆区内存的重复释放 需要利用深拷贝解决

4.6 初始化列表

注意第八行冒号的位置

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

class person
{
public:
	person(int a, int b, int c) :age(a), height(b), money(c) {};
	void show() {
		cout << age <<height<< endl;
	}
public:
	int age;
	int height;
	int money;
};

int main() {
	person p(1,2,3);// person p(1);===person p=1;===person p=person(1);构造方式一样  一般都用括号方式构造
	p.show();
	return 0;
}
4.7类的对象作为类的成员
#include<iostream>
#include <string>
using namespace std;


class phone
{
public:
	phone(string name) :name(name) {
		cout << "phone的构造方法" << endl;
	}
	~phone() {
		cout << "phone的析构方法" << endl;
	}
public:
	string name;
};

class person
{
public:
	// phone p="大哥大"  ----- phone p("大哥大)
	person(string prname, string phname):sname(prname),pname(phname) {
		
		cout << "person的构造方法" << endl;
	}
	~person() {
		cout << "person的析构方法" << endl;
	}
public:
	string sname;
	phone pname;
};
void test() {
	person p("张三","大哥大");
	cout << p.sname << "拿着" << p.pname.name << endl;
}
int main() {
	test();
	return 0;
}
4.8 静态成员
  • 静态成员变量
    • 所有对象共享一份数据
    • 在编译阶段分配内存
    • 类内声明,类外初始化
  • 静态成员函数
    • 所有对象共享一个函数
    • 静态成员函数只能访问静态成员变量
#include<iostream>
#include <string>
using namespace std;

class person
{
public:
	static int a;//静态变量内部定义 内外初始化 见第11行
	static void getA() {
		cout << "a的结果为:" << a << endl;//静态函数不能使用非静态变量aaa
	}
	int aaa;
};
int person::a = 0;

void test() {
	person::getA();
}
int main() {
	test();
	return 0;
}
4.9c++ 对象模型和this指针
  • 空对象占用的内存为1字节
  • 只有非静态成员变量属于类的对象上
class a{
    
}//空类大小为1字节

class a{
    int a;
}//此时类大小为4字节
4.10 this 指针
  • this指针指向被调用的成员函数所属对象
  • 类的非静态成员函数中返回对象本身 *return this
#include<iostream>
#include <string>
using namespace std;

class person
{
public:
	person(int  name) {
		this->name = name;
	}
	void show() {
		cout << this->name << endl;
	}
	person& addPerson(person p2) {
		this->name += p2.name;
		return *this;//可以使用链式编程 返回函数自身
	}
	int name;
};


void test() {
	person p(33);
	person P2(33);
	p.addPerson(33).addPerson(33);//链式编程
	p.show();
}
int main() {
	test();
	return 0;
}
4.11空指针调用成员函数
#include<iostream>
#include <string>
using namespace std;

class person
{
public:
	person(int  name) {
		this->name = name;
	}
	void show() {
		if (this == NULL)//增加程序的健壮性
		{
			cout << "空指针访问" << endl;
			return;
		}
		cout << this->name << endl;
	}

	int name;
};

int main() {
	person* p = NULL;//空指针
	p->show();
	return 0;
}
4.12 const 修饰成员函数

常函数

  • 成员函数后加const称之为常函数

  • 常函数内部不可以修饰成员属性

  • 成员属性添加mutable关键字后可以修改

常对象

  • 声明对象之前添加const称之为常对象

  • 常对象只能调用常函数

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

class person
{
public:
	person(int name, int money) {
		this->money = money;
		this->name = name;
	}
	void show() const { //常函数
		//this->name = 100;
		this->money = 100;
		cout << this->name << endl;
	}
	void fun() {};
	int name;//常函数不能修改
	mutable int money;//常函数可以修改
};


void test() {

}
int main() {
	const person p(12, 13);

	p.show();
	//p.fun();//常对象只能调用常函数
	return 0;
}
4.13友元 friend
  • 全局函数做友元

    #include<iostream>
    #include <string>
    using namespace std;
    // 全局函数友元
    class Building
    {
    	friend	void goodGayvisit(Building* p);//全局函数的友元
    public:
    	Building();
    	~Building();
    	string sittingRoom;
    private:
    	string bedRoom;
    };
    
    Building::Building()
    {
    	this->sittingRoom = "客厅";
    	this->bedRoom = "卧室";
    }
    void goodGayvisit(Building* p) {//全局函数访问
    	cout << "好基友访问客厅" << p->sittingRoom << endl;
    	cout << "好基友访问卧室" << p->bedRoom << endl;
    }
    Building::~Building()
    {
    	cout << "Building 的析构函数" << endl;
    }
    void test() {
    	Building p;
    	goodGayvisit(&p);//函数参数需要指针,在此传递地址
    
    }
    int main() {
    	test();
    	return 0;
    }
    
  • 类做友元

    #include<iostream>
    #include <string>
    using namespace std;
    // 类友元
    class BUiling
    {
    	friend class gay;//友元类
    public:
    	BUiling();
    	~BUiling();
    	string sitting;
    private:
    	string bed;
    };
    
    BUiling::BUiling()
    {
    	this->bed = "卧室";
    	this->sitting = "客厅";
    }
    
    BUiling::~BUiling()
    {
    }
    class gay
    {
    public:
    	gay();
    	~gay();
    	BUiling* bu;
    	void visit(BUiling* bu);
    private:
    
    };
    
    gay::gay()
    {
    	bu = new BUiling;
    }
    void gay::visit(BUiling* p) {
    	cout << p->sitting << endl;
    	cout << p->bed << endl;//私有属性不可访问 需添加友元
    }
    gay::~gay()
    {
    }
    void test() {
    	gay gg;
    	BUiling p;
    	gg.visit(&p);
    
    }
    int main() {
    	test();
    	return 0;
    }
    
  • 成员函数做友元

    与上述函数一致 加上友即可

4.14 运算符重载四则运算

可以进行函数重载

#include<iostream>
#include <string>
using namespace std;
// 运算符重载

class Person
{
	friend Person operator-(Person& a, Person& b);
public:
	Person();
	~Person();

public:
	int a;
	int b;
};


Person::Person()
{
	a = 3;
	b = 3;
	cout << "程序构造初始化" << endl;
}
Person operator-(Person& a, Person& b) {
	Person tem;
	tem.a = a.a + b.a;
	tem.b = a.b + b.b;
	return tem;
}
Person::~Person()
{
	cout << "程序析构退出" << endl;
}

void test() {
	Person p1;
	p1.a = 1;
	p1.b = 2;

	Person p2;
	p2.a = 3;
	p2.b = 4;
	Person p3 = p1 - p2;
	cout << "a=" << p3.a << "b=" << p3.b << endl;

}
int main() {
	test();
	return 0;
}
4.15 左移运算符重载

就是重新定义输出 cout 使之可以直接对对象进行输出

4.16 递增运算符重载

<< ++ – == !=

int a = 10;
	cout << a++ << endl;// a=10
cout<<a<<endl;//a=10
int b=10;
cout<<++b<<endl;//b=11
cout<<b<,endl;/b=11
    int *a;表示将数据防在堆区 需要使用 new int (a)进行申请初始化 需要在析构函数中进行 delete a 进行释放
    
   // 返回自身 使用*this  则函数使用 A&进行返回引用,才是返回真正的自身 不加& 就是返回值 拷贝一份一样的数据

1前置递增(++a)返回的是引用

后置递增(a++)返回的是值

仿函数 ()的重载

4.17 匿名函数
#include<iostream>
#include <string>
using namespace std;
// 匿名对象
class MyAdd
{
public:
	int operator()(int a, int b) {
		return a + b;
	}
	MyAdd();
	~MyAdd();
};
int main() {
	MyAdd m;
	cout << m(1, 2) << endl;
	cout << MyAdd()(22, 22) << endl;// 匿名函数
	return 0;
}
5.继承
  • 继承的基本语法 class 子类 :继承方式 父类
#include<iostream>
#include <string>
using namespace std;
// 继承

class Base
{
public:
	Base();
	~Base();
	void head() {
		cout << "head" << endl;
	}
	void body() {
		cout << "body" << endl;
	}
	void bottom() {
		cout << "bottom" << endl;
	}

private:

};
class son : public Base {//son 继承 Base类
public:
	void getson() {
		cout << "子类的方法" << endl;
	}
};
int main() {
	son s;
	s.head();
	s.body();
	s.bottom();
	s.getson();
	return 0;
}
  • 公有继承
  • 保护继承
  • 私有继承

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A5YRKBRO-1637113785262)(C:\Users\15281\AppData\Roaming\Typora\typora-user-images\image-20211102223245261.png)]

5.1 继承中的对象模型

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

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

现有父类构造 --子构造-子析构-父析构

5.2继承中同名成员处理

同名成员–需要添加父类的作用域 Father:: a 否则直接调用就是调用的子类 子类会直接隐藏和父类同名成员函数

5.3继承静态成员函数的处理方式

访问子类中的直接访问

访问父类的需要添加作用域

通过类方式访问 son::Base::method 第一个::表示使用类的方式访问 第二个表示Base的作用域

5.4多继承语法

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

当父类出现成名成员 需要添加作用域

一般不建议使用

5.5 菱形继承

使用虚继承解决数据不一致的问题 virtual 解决子类继承两份相同的数据,导致资源浪费毫无意义

在这里插入图片描述

6.多态
6.1多态的基本概念
  • 多态满足条件
    • 有继承关系
    • 子类重写父类中的虚函数
  • 多态使用条件
    • 父类指针或者引用指向子类对象
#include<iostream>
#include <string>
using namespace std;
// 继承 运行地址晚绑定
class Animal {
public:
	virtual	void speak() {// 不加 virtual 关键字 第24就是打印”动物在说话“
		cout << "动物在说话" << endl;
	}
};

class Cat :public Animal {
public:
	void speak() {
		cout << "小猫在说话" << endl;
	}
};

void dospeak(Animal& animal) {//父类指针或者引用指向子类对象
	animal.speak();
}
int main() {
	Cat cat;
	dospeak(cat);
	return 0;
}
6.2 纯虚函数

当类中有了纯虚函数, 这类成为抽象类

#include<iostream>
#include <string>
using namespace std;
// 继承
class Animal {
public:
	virtual	void speak() = 0;// 纯虚函数 不能够实例化对象 子类必须进行函数重写
};

class Cat :public Animal {
public:
	void speak() {
		cout << "小猫在说话" << endl;
	}
};


int main() {
	Animal* c = new Cat;// 指针的方式可以使得new 其他子类 多态的一种体现
	c->speak();
	delete c;// 堆区使用之后必须进行释放
	return 0;
}
6.3虚析构和纯虚析构

虚析构 可以解决父类指针释放子类对象不干净的问题 ---- 子类有数据开辟到堆区

(* a作为函数参数 可以使用 new A—a是A的实现类)

7文件操作
7.1写文件

在这里插入图片描述
在这里插入图片描述

#include<iostream>
#include <string>
#include<fstream>
using namespace std;
// 文件的读写
int main() {
	ofstream ofs;
	ofs.open("exam.txt", ios::out);
	ofs << "测试" << endl;
    ofs.close();// 文件写之后需要进行文件关闭
	return 0;
}
7.2读文件
#include<iostream>
#include <string>
#include<fstream>
using namespace std;
// 文件读
int main() {
	ifstream ifs;
	ifs.open("exam.txt", ios::in);
	if (!ifs.is_open()) {
		cout << "打开文件失败" << endl;
		return 0;
	}
	string buffer;
	while (getline(ifs, buffer))
	{
		cout << buffer << endl;
	}
	ifs.close();
	return 0;
}
8、c++提高编程
8.1函数模板
#include<iostream>
#include <string>
#include<fstream>
using namespace std;
// 函数模板
template <typename T>
void mswap(T& a, T& b) {
	int tem;
	tem = a;
	a = b;
	b = tem;
}
int main() {

	int a = 1;
	int b = 2;
	// 自动推导确定数据类型
	mswap(a, b);
	// 显示指定其数据类型
	mswap<int>(a, b);
	cout << a << endl;
	return 0;
}
8.2函数模板注意事项
  • 自动类型推导,必须推导出一致的数据类型T,才可以使用
  • 模板必须要确定T的数据类型,才可以使用
8.3普通函数和函数模板的区别
  • 普通函数调用可以发生 *隐式类型转换=====add(10,‘c’)可以将‘c’转换为ASCII编码 99*
  • 函数模板 用自动类型推导,不可以发生隐式类型转换
  • 函数模板 用显式指定类型,可以发生隐式类型转换
  • 函数模板也可以发生重载
8.4类模板和函数模板的区别
  • 类模板没有自动类型推到的使用方式
  • 类模板在模板参数列表中可以有默认参数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RvUuvypT-1637113785266)(C:\Users\15281\AppData\Roaming\Typora\typora-user-images\image-20211103165414699.png)]

8.5 类模板中成员函数的创建时机
  • 普通类中的成员函数一开始就可以创建
  • 类模板的成员函数在调用时才创建
9.STL使用

分为 容器、算法和迭代器

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值