C++ 异常处理入门(try / catch / throw)
程序运行中会出现各种「特殊情况」,导致后续逻辑无法正常执行:文件打不开、内存不足、网络超时、除数为零……这类情况统称为异常。本文介绍 C++ 异常处理的三个关键字、catch 的匹配顺序,以及重新抛出的用法。 一、三个关键字 关键字 作用 try 包裹一段「可能出问题」的代码,检查其中产生的异常 catch 捕获并处理 try 中产生的异常 throw 在 try 块或它调用的函数里,抛出异常 配合使用的基本形态: 12345try { // 可能抛异常的代码} catch (异常类型& e) { // 处理这个异常} try 块里只要有一处 throw 被执行,后面的语句就不再执行,控制流立刻跳到匹配的 catch。 二、第一个例子:除零异常123456789101112131415161718#include <iostream>#include <stdexcept> // runtime_error 所需头文件using namespace std;float div...
C++ 类与面向对象核心知识整理
本文把 C++ 类相关的核心知识点串成一条线:继承 → 函数重写 → 虚函数 → 多态 → 抽象类,再补上 static、const、this、友元等常用特性。 一、头文件保护:#pragma once写多文件程序时,同一个头文件可能被重复 #include(比如 A 和 B 都包含了 shape.h),会导致类被重复定义的编译错误。#pragma once 放在头文件最开头,保证它在一个编译单元里只被展开一次: 123456// shape.h#pragma onceclass Shape { // ...}; 它与老式的 include guard 等价,但更简洁、不易写错: 12345// 老式写法,效果相同#ifndef SHAPE_H#define SHAPE_Hclass Shape { /* ... */ };#endif #pragma once 是编译器扩展(主流编译器都支持),写头文件时优先用它。 二、继承2.1 继承关系示意 graph TD A[Shape] --> B[Circle] A --&g...
C++ 宏定义(#define)详解
宏(macro)是 C/C++ 预处理器提供的文本替换机制,在正式编译之前由预处理器完成替换。本文介绍对象式宏、条件编译、宏函数、# 与 ## 运算符,以及预定义宏,并说明现代 C++ 中宏的替代方案。 一、宏的本质宏不是变量也不是函数,而是编译前的文本替换。比如: 1#define NUM 123 预处理阶段,代码里所有的 NUM 都会被原样替换成 123,然后才进入编译。理解这一点是看懂宏所有「坑」的前提。 二、对象式宏(不带参数)12#define NUM 123 // 定义#undef NUM // 取消定义,之后 NUM 恢复为未定义状态 宏名通常全大写,和普通变量区分(约定俗成,非语法要求); 定义行末尾不要加分号——分号会被一起替换进去,多数场景下多余甚至出错; 宏没有类型,不做类型检查,只是纯文本。 现代 C++ 中,常量优先用 const / constexpr: 1constexpr int NUM = 123; // 有类型、有作用域、编译器会检查,更安全 三、条件编译条件编译指令根据「宏是否被定义」决定某段代码...
C++ 类模板(Class Template)入门
类模板是 C++ 泛型编程的核心。上一篇讲了函数模板,本文接着讲类模板:如何定义、成员函数怎么写、全特化与部分特化、非类型参数、默认参数,以及模板模板参数。 一、为什么需要类模板和函数模板同理:如果为 int、float、double 各写一个 Vector 类,逻辑完全相同,只是元素类型不同。类模板让我们写一份代码,编译器根据实例化时的类型自动生成对应版本。 二、基本定义语法123456789101112template <typename T>class Vec3 {private: T m_v[3];public: Vec3(T v1, T v2, T v3) { m_v[0] = v1; m_v[1] = v2; m_v[2] = v3; } T get(int i) const { return m_v[i]; }}; 使用时用 类名<具体类型> 实例化: 123456789#include <iostream>...
C++ 函数模板(Function Template)入门
函数模板是 C++ 泛型编程的基础。本文从「为什么需要模板」讲起,依次介绍模板的定义、实例化、多类型参数、重载与特化,最后整理几个初学者常踩的坑。 一、为什么需要函数模板假设要写一个求两个数较大值的函数,不用模板就得为每种类型重载一遍: 1234int max(int a, int b) { return a > b ? a : b; }double max(double a, double b) { return a > b ? a : b; }char max(char a, char b) { return a > b ? a : b; }// 每多一种类型就要再写一遍,逻辑完全相同…… 这些函数的逻辑一模一样,只是参数类型不同。函数模板让我们只写一份代码,由编译器根据调用时的类型自动生成对应版本。 二、定义语法12template <class T> // class 是 C++ 关键字,在这里表示「任意类型」template <typename T...
最大公因数与最小公倍数(GCD 与 LCM)
最大公因数(GCD)和最小公倍数(LCM)是数论中最基础的两个概念,很多算法题都会用到。本文先理清定义,再给出基于辗转相除法的 C++ 实现。 一、基本概念因数能整除某个整数的整数,称为这个整数的因数。例如 6 的因数有 1、2、3、6。 公因数如果一个整数同时是几个整数的因数,就称它为这几个整数的公因数;其中最大的一个就是最大公因数(greatest common divisor,GCD)。 公倍数在两个或两个以上的自然数中,如果它们有相同的倍数,这些倍数就是它们的公倍数;其中最小的一个就是最小公倍数(lowest common multiple,LCM)。 二、热身:几组数 a b 最大公因数 gcd 最小公倍数 lcm 12 18 6 36 15 25 5 75 可以先自己想一想:6 和 36、5 和 75 是怎么来的? 三、最大公因数 GCD英文三个单词正好对应它的含义: greatest:最大的 common:共同的 divisor:因数 辗转相除法(欧几里得算法)这是求 GCD 最经典的方法:不断用较大数除以较小数,把「除数」和「余数」作...
有关蛇形方阵的几种题目和解题思路
蛇形方阵是模拟类题目的经典入门题,核心在于按照「右 → 下 → 左 → 上」的顺序转圈填数。本文记录两道相关题目: 题目一 P5731:两种经典模拟写法; 题目二 P2239:在模拟之外,更进一步的 O(1) 数学解法。 题目一:洛谷 P5731 蛇形方阵题目链接:P5731 【深基5.习6】蛇形方阵 方法一:4 个 while 循环用四个 while 分别控制「右、下、左、上」四个方向的填充。每个方向一直走,直到越界或格子已有值,然后回退一格、转向 90°。 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556#include<iostream>#include<vector> #include<cstdio>using namespace std;int main(){ int n; cin>>n; vector<vector<int>>...
对异或运算符的学习路程
最近在刷洛谷时遇到了 P1161 开灯 这道题,发现了一种非常巧妙的异或解法。本文从常规的数组模拟讲起,再到异或消去,并整理异或运算符的几条核心性质。 方法一:朴素算法 —— 数组模拟思路用一个巨大的 bool 数组记录每盏灯的状态,每经过一次就将对应位置取反(开灯 ↔ 关灯),最后遍历整个数组,找到唯一仍亮着的灯。 1234567891011121314151617181920212223#include<iostream>#include<vector>using namespace std;int main(){ int n; double a,t; vector<bool> b(2000001,0); cin>>n; for(int i=0;i<n;i++){ cin>>a>>t; for(int j=1;j<=t;j++){ int tmp=a*j; b[tmp]=!b[tmp]; } } for(int i=0;i&l...
Hello
欢迎来到我的博客。 这是用 Hexo + Butterfly 主题重新搭建后的第一篇文章,博客部署在 Vercel 上。图床使用了 imgdd。


