C++核心知识点整理笔记

C++核心知识点整理笔记

本篇笔记系统性地整理了C++面向对象编程的核心概念,涵盖了从基础封装、构造函数/析构函数,到高级特性如继承、多态、模板、容器等关键内容,并辅以代码示例,适合学习和回顾。

封装

核心概念

  • 核心思想:将数据与操作数据的函数绑定在一个结构(类)中,实现信息隐藏和数据安全。
  • 类 (class) :相当于C语言的结构体的升级,可包含成员变量和成员函数。

访问权限控制:

public:公有,类内外部均可访问。

private:私有,仅本类内部可访问。

protected:受保护,本类和派生类可访问。

class base//类定义
{
	public://公有
    int a;
    int b;
    
    void Init()
    {
        this->a = 1;
        this->b = 2;
        this->c = 3;
        this->d = 4;
    }
    
    int add();//声明 定义在下面
    
    private://私有
    int c;
    
    protected://受保护
    int d;
}

// 成员函数在类外定义
int base::add()//打个标签 base对象里面的
{
    return this.a + this.b;
} 

int main()
{
  base test;
  test.Init();
  test.a = 100;
  return 0;  
};

核心要点

  • 结构体首地址给ecx this—>[ebp-0x4]
  • 成员函数不占用类的对象空间,只存储一份代码。
  • 反汇编中,对象会多分配4个字节(32位)用于存储this指针(通常位于[EBP-0x4]),这时候,第1个变量是 [EBP-0x8] 开始,依次类推
  • C++过程中只要对本对象操作的函数 全部都要封装在一起

构造函数与析构函数

构造函数

功能:对象创建时自动调用,用于初始化成员变量。

特点

  1. 函数名与类名完全相同。
  2. 无返回值类型。
  3. 参数可有,可没有
  4. 构造函数传参的时候,先判断参数个数,在判断参数类型
  5. 无参数的构造函数称为缺省构造函数
class base
{
	public://公有
    int a;
    int b;
    
    base(int x, int y)
    {
        this->a = x;
        this->b = y;
    }
    base();//定义构造函数
}

base::base()//缺省的构造函数
{
}

int main()
{
  base test(2,3);
  return 0;  
};

多个构造函数:

  1. 看参数的个数
  2. 如果参数的个数一样,在看参数的类型
class base
{
	public://公有
    int a;
    int b;
    char c;
    
    base(int x, int y);
    base(int x, char y);
}

base::base(int x, int y)
 {
    this->a = x;
    this->b = y;
 }
base::base(int x, char y)
 {
    this->a = x;
    this->c = y;
 }

int main()
{
  base test(2,3);
  base test(2,'A');
  return 0;  
};

析构函数

功能:对象销毁(生命周期结束)时自动调用,用于清理资源。

特点

  1. 函数名为类名前加波浪线~
  2. 释放对象,有多少对象,就释放多少次
  3. 函数名与类名完全相同。
  4. 无返回值,无参数。
  5. 一个类有且只有一个析构函数。
class base
{
	public://公有
    int a;
    int b;
    char c;
   
    base(int x, int y)//构造函数
    {
        this->a = x;
        this->b = y;
    }
    
	~base()//析构函数
	{	
		cout << "释放了" << endl;
	}
}

int main()
{
  base test(2,3);
  base test(2,'A');
  return 0;  
};

继承

核心概念

  • 继承:派生类(子类)继承基类(父类)的成员,实现代码复用和层次化设计。他的成员变量是放在对象的最上面,第1个继承的对象,始终在最上面,只要继承了那就是派生类。
  • 派生类对象的内存布局中,基类成员位于最上方
  • 继承方式:public, protected, private
#include <iostream>

//父亲 基类 父类
class student1
{
//公有    
public:
	int a;
//私有 只有本对象可以用
private:
	int e;
//受保护 可以被继承
protected:
	int g; 
};

//母亲 基类 父类
class student2
{
public://公有
	int f;
};

//儿子 派生类 子类   继承多个打逗号student1和student2
class student:public student1,public student2
{
public://公共
	int a;
	int b;
	int c;
};

int main()
{
	student aa;

	aa.a = 1;;//ebp-0xC
	aa.b = 2;//ebp-0x8
	aa.c = 3;//ebp-0x4
	aa.student1::a = 1;//ebp-0x14  加作用域代表哪个对象里面
    aa.f = 5;//ebp-0x10

	return 0;
}

继承构造函数

  • 派生类可调用基类构造函数初始化继承来的成员。
#include <iostream>

using namespace std;

class base
{
//公有
public:
    int a;
    int b;
    
    base()
    {
    }
    base(int x,int y)
    {
        this->a = x;
        this->b = y;
    }
    ~base()
    {
    }
};

class student: public base
{
public:
	student(int d,int e,int g):base(d,e),f(g)//继承base析构函数 初始化  只有继承了 才使用f(g)赋值方式
    {	
    }
    ~student()
    { 
    }
	void init()
	{
		cout << this->a << endl << this->b << endl << this->f << endl;
	}
private:
	int f;
};

int main()
{
	base aa;

    student bb(1,2,3);
	bb.init();
    
    return 0;
}

运算符重载

  • 关键字:operator,后面加运算符 (简单来说就是给函数名字 起个名字)
  • 功能:为用户自定义类型(类)重新定义运算符的行为。
#include <iostream>

using namespace std;

class base
{
public:
	int a;
	int b;

	base(int i1,int i2)//构造函数
	{
		this->a = i1;
		this->b = i2;
	}
	~base()//析构函数
	{
	}

	void operator-(int c)//运算符重载
	{
		c = this->a - this->b;
		cout << c << endl;
	}
	void operator+(int c)//运算符重载
	{
		c = this->a + this->b;
		cout << c << endl;
	}
};

int main()
{
	int r = 0;
	base aa(1,2);

	aa.operator+(r);

	return 0;
}

模板

函数模板

  • 关键字:template<typename/class name>
  • 功能:编写与数据类型无关的通用函数。
#include <iostream>

using namespace std;

//函数模板
template<typename temp,typename temp1>
temp add(temp a, temp1 b)
{
	temp c;

	c = a + b;

	cout << "add: "<< c << endl;

	return c;
}

int main()
{
    
	add(1,2);
	add((short)1,(short)2);
	add((long)10000000,(long)20000000);

	return 0;
}

类模板

  • 功能:定义可处理多种数据类型的通用类。
  • 每个函数都要加上模板
  • 告诉它处理什么类型数据的放括号里面<T>
  • 定义类的时候要传入类型告知是int char short类型 Stack<char> s;
  • 注意:每个成员函数定义前都需再次声明模板。
#include <iostream>
#include <cstdlib>
using namespace std;

template<typename T>//每个函数都加上
class Stack
{
	typedef struct node
	{
		T value;
		struct node* pnext;

	}NODE,*PNODE;

public:
	void init();
	void push(T value);
	void show();

private:
	PNODE s_esp;
	PNODE s_ebp;
};

template<typename T>//每个函数都加上
void Stack<T>::init()
{
	this->s_esp = this->s_ebp =(PNODE)malloc(sizeof(NODE));
	if (this->s_esp == NULL)
	{
		cout << "分配内存失败!" << endl;
	}

	this->s_ebp->pnext = NULL;
}
template<typename T>//每个函数都加上
void Stack<T>::push(T value)
{
	PNODE pNew = (PNODE)malloc(sizeof(NODE));
	if (pNew == NULL)
	{
		cout << "分配内存失败!" << endl;
	}

	pNew->value = value;
	pNew->pnext = this->s_esp;
	this->s_esp = pNew;
}
template<typename T>//每个函数都加上
void Stack<T>::show()
{
	PNODE p = this->s_esp;

	while ( p != this->s_ebp )
	{
		cout << p->value << endl;
		p = p->pnext;
	}
}

int main()
{
	Stack<char> s;//可以传char int long char*...
	s.init();
    
	s.push('A');
	s.push('B');
	s.push('C');
	s.push('D');
	s.push('E');
	s.show();
    
	return 0;
}

命名空间

  • 功能:避免命名冲突,将全局作用域划分为不同的区域。
  • 关键字:namespace, using
#include <iostream>

//using std::cout;
//using std::cin;
//using std::endl;

//自己定义的命名空间
namespace myname
{
	int res;

	int add(int a, int b)
	{
		return a + b;
	}

	class student
	{
	public:
		int a;
	};
}

//所有东西都是放在这里std命名空间里面 这样就调用就不需要加上std:: 
using namespace std;

//放到命名空间里面 下面就不需要加上myname::进行访问了
using namespace myname;

int main()
{
//	res = myname::add(1, 2);
	res = add(1, 2);

//	myname::student aa;
//	aa.a = 88;

	student aa;
	aa.a = 88;

	cout << res << "\t" << aa.a << endl;

	char str[20];

	cout << "命名空间" << endl;
	cin >> str;
	cout << str << endl;

	return 0;
}

虚函数与多态

虚函数

  • 关键字:virtual
  • 功能:实现运行时多态。通过基类指针或引用调用派生类的重写函数。
  • 原理:包含虚函数的类会增加一个虚表指针 (vptr),指向一个虚函数表 (vtable),表中存放实际的函数地址。

核心要点

  • 什么是虚函数:在函数的前面加上 virtual
  • 用基类去访问派生类,函数原型要一样
  • 虚函数多分配的四字节,放的是虚表指针
  • 虚表指针里面放的是,函数的地址(派生类)
  • 虚函数只能在对象里面的函数加 构造函数不能加 全局变量不能加
#include <iostream>

using namespace std;
//基类
class base
{
public:
	int value;

	virtual void fun()//虚函数
	{
		printf("基类--->base fun调用\n");
	}
};
//派生类
class student:public base
{
public:
	int value;

	virtual void fun()//虚函数 可加可不加 virtual
	{
		printf("派生类--->student fun调用\n");
	}
};

int main()
{
	student aa;
	base* bb;

	bb = &aa;

	bb->fun();
	
	printf("base = %d\tstudent = %d\n",sizeof(base),sizeof(student));
	return 0;
}

纯虚函数与抽象类

  • 纯虚函数:virtual void fun() = 0;
  • 抽象类:包含至少一个纯虚函数的类。不能实例化对象,仅为派生类提供接口规范。
  • 纯虚函数:父类(基类)没有完成的事情交给子类(派生类)去完成
class base
{
	public:
	int a;
	
	virtual void fun() = 0;//纯虚函数
}

class student:public base
{
    virtual void fun()
    {
        cout << "被调用了" << endl;
    }
};

多态应用示例

#include <iostream>
#include <string>

using namespace std;

//动物
class base
{
public:

	virtual void init()
	{
		cout << "base init--->被调用了" << endl;
	}

	virtual void put()
	{
		cout << "base put--->被调用了" << endl;
	}
};
class Cat : public base
{
public:
	string name;

	virtual void init()
	{
		this->name = "猫";
	}
	
	virtual void put()
	{
		cout << "动物名字: " << this->name << endl;
	}
};
class Sheep : public base
{
public:
	string name;
	
	virtual void init()
	{
		this->name = "羊";
	}
	
	virtual void put()
	{
		cout << "动物名字: " << this->name << endl;
	}
};
class Ox : public base
{
public:
	string name;
	
	virtual void init()
	{
		this->name = "牛";
	}
	
	virtual void put()
	{
		cout << "动物名字: " << this->name << endl;
	}
};
class Dog : public base
{
public:
	string name;
	
	virtual void init()
	{
		this->name = "狗";
	}
	
	virtual void put()
	{
		cout << "动物名字: " << this->name << endl;
	}
};
class Crocodile : public base
{
public:
	string name;
	
	virtual void init()
	{
		this->name = "鸟";
	}
	
	virtual void put()
	{
		cout << "动物名字: " << this->name << endl;
	}
};

int main()
{
	Cat aa;
	Sheep bb;
	Ox cc;
	Dog dd;
	Crocodile ee;

	base* animal[] = { &aa,&bb,&cc,&dd,&ee };
	int i;

	for ( i = 0; i < sizeof(animal)/sizeof(base*); i++ )
	{
		animal[i]->init();
		animal[i]->put();
		cout << endl;
	}

	return 0;
}

STL容器

核心容器简介

  1. vector:动态数组。插入/删除数据慢,支持随机访问,查找和排序快。
  2. list:双向链表。在任何位置插入/删除都快,但不支持随机访问。
  3. deque:双端队列。综合能力强,两端插入/删除快。

vector 基本用法

#include <iostream>
#include <vector>
#include <string>

int main()
{
	using namespace std;

	//定义容器
	vector<int> v1;
	//定义容器 默认的初始化为0
	vector<string> v2(10);
	//定义容器 传对象的时候类型必须一样
	vector<string>v3(v2);
	//定义容器 b[10] = {2,2,2,2,2,2,2,2,2,2};
	vector<int> v4(10, 2);

	//添加数据
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(3);
	v1.push_back(4);
	v1.push_back(5);

	//遍历数据 常规
	for (vector<int>::size_type i = 0; i < v1.size(); i++)
	{
		cout << v1[i] << endl;
	}

	//循环添加数据
	for (vector<int>::size_type i = 0; i < 5; i++)
	{
		// cin >> v1[i]; //C++不允许这么操作
		// cin >> i;
		v1.push_back(i);
	}

	//遍历数据 指针
	for (vector<int>::iterator p = v1.begin(); p != v1.end(); p++)
	{
		cout << *p << endl;
	}

	return 0;
}

文件流

核心类

  • ofstream:输出文件流,用于写文件(派生自ostream)。
  • ifstream:输入文件流,用于读文件(派生自istream)。
  • fstream:输入输出文件流,用于读写文件(派生自iostream)。
图片[1]-C++核心知识点整理笔记-萝莉猫博客

文件打开模式

模式常量含义
ios_base::inios_base::in
ios_base::out打开文件,用于写入
ios_base::ate打开文件立即将文件定位在文件尾
ios_base::app追加模式,写入到文件末尾
ios_base::trunc打开时清空文件内容
ios_base::binary以二进制模式打开

注意:out | appapp|trunc 不能共存

示例:读取文件

#include <fstream>
#include <string>
using namespace std;
int main() {
    ifstream file("data.txt"); // 默认以 in 模式打开
    string s;
    if(!file) { cerr << "打开文件失败!" << endl; }
    file >> s; // 读取一个字符串
    cout << s << endl;
    file.close();
    return 0;
}
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容