c++笔记2
14、c++的对象
对象和结构的区别;
结构:包含各种类型的变量;
对象:包含各种函数、和变量;
设计对象的时候引用class关键字创建类,和结构形状差不多;
将变量称之为属性,函数称之为方法;
14造车,创建类:类的实际应用;
一个awm型号的车;
属性(c变量):车身颜色、油
方法(c函数):改变颜色、加油;
类的声明和定于;
#include <iostream>class MyClass_che
{
public:MyClass_che();~MyClass_che();std::string yanse;void gaibian_yanse(std::string);int you;void gaibian_you(int);private:};
void MyClass_che::gaibian_yanse(std::string str)// ::表域符 ,指示实在这个类里面的方法/或属性
{MyClass_che::yanse = str;
}
void MyClass_che::gaibian_you(int you)
{MyClass_che::you = you;
}
类定义时候:不能对常量赋值,除非是加static
awm a;创建了一个对象a属于awm型号的车
以上结合就理解了这就是对象;这个对象有颜色、油属性;有改变颜色、改变油的方法;
作用域 ::表域符 ,指示是在这个类里面的方法/或属性
同类对象可以赋值;
awm a,b;
b=a;
16构造器
构造器和通常方法的主要区别;
-构造器的名字必须和它所在的类的名字一样;
-系统在创建某个类的实例时会第一时间自动调用这个类的构造器;
-构造器永远不会返回任何值
构造器如下
构造器定义如下;相当于一个函数,没有viod,且在声明创建一个对象后被执行;(相当于c里面的 回调函数,创建一个对象就回调)
MyClass_che::MyClass_che()
{
}
每个类至少一个构造器;没写构造器,编译器也会给你定义一个构造器( 内容为空 );
析构器
属性和构造器一样;不过前面加~波浪线
程序结束时调用:该程序使用内存,就在析构器里面释放内存
应用
比如构造器打开文本:打开文本需要内存
,析构器关闭文本 ; 关闭文本就释放了内存
#include <iostream>
#include<fstream>
class MyClass_che
{
public:MyClass_che();~MyClass_che();std::string yanse;void gaibian_yanse(std::string);std::fstream pf;int you;void gaibian_you(int);private:};MyClass_che::MyClass_che()
{pf.open("123.txt", std::ios::in | std::ios::out);
}MyClass_che::~MyClass_che()
{pf.close();
}
17this的继承和类的继承
this指针,表当前方法的所属类;
void MyClass_che::gaibian_you(int you)
{MyClass_che::you = you;this->you = you;//此时的this等效于MyClass_che,右边的you代表形参,左边代表这个类的属性
}
基类:
子类;
两个类的描述:
基类是公共有的,子类继承基类,并且多于基类的属性和方法;
例如;
动物是基类
{
吃饭、睡觉
}
甲鱼子类、猪是子类
甲鱼
{
基类的属性和方法
独特属于甲鱼的属性:游泳
}
猪
{
基类的属性和方法
独特属于猪的属性:上树
};
#include <iostream>
class dongwu//基类
{
public:dongwu();~dongwu();void eat();private:};void dongwu::eat()//基类方法
{std::cout << "我在吃饭" << std::endl;
}
dongwu::dongwu()
{
}dongwu::~dongwu()
{
}
class pig:public dongwu//pig 继承于(分号) dongwu
{
public:pig();~pig();void shangshu();//属于猪的独特属性private:};pig::pig()
{
}pig::~pig()
{
}
void pig::shangshu()
{std::cout << "上树了" << std::endl;
}int main()
{pig pig1;//构建一只猪1对象,类别是子类pigpig1.eat();//这是继承的基类的方法pig1.shangshu();//这是子类特有的std::cout << "Hello World!\n";
}
18子类的构造器和析构
创建对象时:
先执行父类的构造器
才到子类的构造器;
销毁对象时:
子类的最后一条语句结束后调用基类的析构器;
- 首先调用子类的析构器。
- 然后调用父类的析构器。
带参数的构造器声明
父类,基类
class dongwu
{
public:dongwu( std::string N_name);//带参的基类析构函数~dongwu();private:};
子类
class pig:public dongwu//继承父类的子类
{
public:pig(std::string N_name);//带参的子类析构函数~pig();private:};
构造器定义
带参子类构造器的定义
//子构造器的形式 子构造器 :父类构造器(不带类型 的参数)
dongwu::dongwu(std::string N_name)
{
name = N_name;
}
这个name = N_name;
个人认为是:相当于tihs->name = N_name; 初始化了tihs->name;
然后再继承给子类
pig::pig(std::string N_name):dongwu::dongwu( N_name)//子构造器的形式 子构造器 :父类构造器(不带类型 的参数)
{
}
子类析构器
编译器自动添加;可不用处理;
19访问控制
类的属性和方法有访问控制
访问控制可以在编译的时候编译器可以检查到合法性;
在声明类的时候,访问控制如下关键字
public: 公共 此下的属性和方法 可以被任何代码访问
protected: 保护 此下的属性和方法,可以被这个类本身方法和子类方法访问
1、外部代码无法通过过子类去调用父类的保护
private: 私有 此下的属性和方法,只有这个类本身可以访问
class dongwu
{
public://任何代码都可以访问dongwu( std::string N_name);//带参的基类析构函数~dongwu();std::string name;protected://子类方法内和这个类方法内可以访问int a;
private://只能 dongwu temp;由这个类的 temp 访问int b;};
main函数里面无法找到a和b;a被保护 b是私有;
在pig类方法里面,可以引用父类的被保护的a;
pig::pig(std::string N_name):dongwu::dongwu( N_name)//子构造器的形式 子构造器 :父类构造器(不带类型 的参数)
{//name = N_name;this->a = 0;
}
20覆盖函数和重载
覆盖如下:
子类继承了父类的eat()方法,
子类中又声明且定义了eat()的方法,此时子类调用的eat方法,就会覆盖继承父类的eat();
所以子类调用的时候,调用的方法其实就是子类的eat();
class dongwu
{
public://任何代码都可以访问dongwu( std::string N_name);//带参的基类析构函数~dongwu();std::string name;void eat();protected://子类方法内和这个类方法内可以访问int a;
private://只能 dongwu temp;由这个类的 temp 访问int b;};void dongwu::eat()//父类的
{std::cout << " eat \n";
}
class pig:public dongwu//继承父类的子类
{
public:pig(std::string N_name);//带参的子类析构函数~pig();void eat();private:};void pig::eat()//子类的
{std::cout << "吃到了 大蛋糕";
}
重载
通过重载等效覆盖,通过改变子类的参数个数,或者参数类型,就可以保留继承父类的eat()
C++学习笔记-CSDN博客
参考其中的章节: 06:函数的重载
class dongwu
{
public://任何代码都可以访问dongwu( std::string N_name);//带参的基类析构函数~dongwu();std::string name;void eat();protected://子类方法内和这个类方法内可以访问int a;
private://只能 dongwu temp;由这个类的 temp 访问int b;};void dongwu::eat()//父类的
{std::cout << " eat \n";
}
class pig:public dongwu//继承父类的子类
{
public:pig(std::string N_name);//带参的子类析构函数~pig();void eat(int);private:};void pig::eat(int)//子类的
{dongwu::eat();//只要前面文本定义了这个 方法就可以直接这样调用std::cout << "吃到了 大蛋糕";
}
补充: dongwu::eat();//只要前面文本”定义 “了这个 方法就可以直接这样调用
21友元关系
在aa类声明的时候添加
friend class bb;//指定友元为bb,所以类bb可以访问aa的保护
#include <iostream>
class aa
{
public:
protected:int k1;
private:friend class bb;//指定友元为bb,所以类bb可以访问aa的保护
};class bb
{
public:void set(class aa* k);
protected:int y1;
private:
};void bb::set(class aa * k)//传递aa的类指针
{k->k1 = 0;//调用了aa的保护属性,无错误,所以可以调用
}int main()
{std::cout << "Hello World!\n";
}
22、静态属性和静态方法
静态成员
1、需要在外部定义和初始化
2、只需要在类里面声明;
3、静态成员先于类,不是独特地属于任何类;
静态成员是所有同类对象共享的,再静态方法里面不能访问普通成员;
普通方法可以访问静态成员和方法;
this指针
1、this指针每个类自动生成的私有成员
2、当一个对象被生成的时候,该对象的this指针就指向了对象的首地址
3、任何方法都可以用this指针,这个this指针是隐藏传送到方法里面的;get()其实是get(类指针* this );方法被调用指针就传入;
4、this可以指向每个成员和方法
结论:所以静态方法不属于任何对象,所以无法确定为对象地址,所以无法使用this指针;
调用方法坚持使用 类::方法;可以提高代码阅读性
如cat::get();
静态成员共享例子
#include <iostream>
#include <string>using namespace std;
class dongwu
{
public:dongwu(std::string N_name);~dongwu();static int get_cout();int get();std::string name;private:static int cout;int a;};
int dongwu::cout = 0;
int dongwu::get_cout()
{
// a++; 会编译错误return cout;
}
int dongwu::get()
{return cout;
}
dongwu::dongwu(std::string N_name)
{name = N_name;cout++;std::cout << name<<cout;
}dongwu::~dongwu()
{cout--;
}
class cat:public dongwu
{
public:cat(std::string N_name);
};
cat::cat(std::string N_name):dongwu::dongwu(N_name)
{
}int main()
{cat a1("小猫");cat a2("小猫");std::cout << '\n' << a1.get()<<'\n';{cat a3("小猫");cat a4("小猫");std::cout << '\n' << a1.get_cout() << '\n';}std::cout << '\n' << a1.get_cout() << '\n';
}
24虚方法;
虚方法关键字 在类的声明里面的方法添加关键字virtual
class dongwu
{
public:dongwu(std::string N_name);~dongwu();std::string name;virtual void play();///虚方法
private:static int cout;};
应用场景:
//指针是基类,创建的内存是子类;导致调用子类方法不能覆盖,必须用虚方法解决
#include <iostream>
#include <string>using namespace std;
class dongwu
{
public:dongwu(std::string N_name);~dongwu();std::string name;virtual void play();///虚方法
private:static int cout;};
dongwu::dongwu(std::string N_name)
{name = N_name;
}
void dongwu::play()
{std::cout << "动物在玩";
}dongwu::~dongwu()
{
}
class cat:public dongwu
{
public:cat(std::string N_name);void play();};
cat::cat(std::string N_name) :dongwu(N_name)
{}
void cat::play()//子类方法
{std::string str=this->name;str.append("这只猫再玩毛线");std::cout << str;
}int main()
{dongwu* p = new cat("小花");//指针是基类,创建的内存是子类;导致调用子类方法不能覆盖,必须用虚方法解决p->play();//如果基类不加virtual 虚方法关键字 ,方法是基类方法,子类没有成功覆盖}
补充:
new 创建内存
delete 删除内存
new cat ;创建了一个子类内存
delete :释放了一个子类的内存
25、纯虚方法
纯虚方法:
在虚方法后面=0;
作用,优化代码,告诉编译器,不需要寻找执行实现,这是一个纯虚方法,任何都可以覆盖,也可以说不用可以去覆盖了,每个继承的都可以无顾虑的实现覆盖;
多态性:
一个名字,可以执行不同的操作;
编译时的多态:通过重载实现,编译时运行快
运行时的多态:通过虚函数实现,运行时灵活和抽象
析构函数就是虚方法;
是为了当基类指针删除子类对象时,正确调用子类析构函数;
思路(仅仅为了理解):相当于为了覆盖子类方法,用虚方法,使得调用方法时是执行子类方法,而不是基类的方法;
特别说明:基类被继承后,基类的析构才是虚函数;
26、运算符重载
以下5个运算符不允许重载
. (成员访问运算符)
.* 成员指针访问运算符(本人认为 ->)
::域运算符
sizeof( ) (尺寸运算符)
?: (条件运算符)
运算符重载形式:
函数类型 operator 运算符(参数列表);
Complex operator +(Complex&d);//重载运算符 相当于返回值类型为Complex类
当 Complex类 遇到加号 且后面为同类Complex,运算符执行如下(函数运算)
例子如下备注,仅个人理解
#include <iostream>
class Complex
{
public:Complex();~Complex();Complex(double r, double i);Complex operator +(Complex&d);//重载运算符 相当于返回值类型为Complex类 当 Complex类 遇到加号 且后面为同类Complex,运算符执行如下运算void print();private:double real;double imag;
};Complex::Complex()
{
}Complex::~Complex()
{
}Complex::Complex(double r, double i)//重载函数
{real = r;imag = i;
}
Complex Complex::operator +(Complex& d)//括号里面的是类对象,传入对象 运算符重载
{Complex c;c.imag = imag + d.imag;c.real = real + d.real;return c;
}void Complex::print()
{std::cout << "(" << real << "," << imag << "i)";
}int main()
{Complex c1(1.0, 2.0), c2(3.0, -4.0), c3;c3 = c1 + c2;//该对象是Complex类遇到+,发生了重载,使用指定的运算int a, b=8, c=9;a = b + c;c3.print();std::cout << "Hello World!\n"<<a;
}
小鱼理解:
c1+c2
c1.operator+(c2);编译器理解为,相当于调用一个函数得到返回值
运算符重载作为类友元函数
运算符重载
Complex operator +(Complex &a, Complex &b)//在类中被声明了友元,所以可以访问私有;这同时是个运算符重载
{return Complex(a.real + b.real, a.imag + b.imag);//
}
在类里面声明为友元
class Complex
{
public:Complex();~Complex();Complex(double r, double i);// Complex operator +(Complex&d);//重载运算符 相当于返回值类型为Complex类 当 Complex类 遇到加号 且后面为同类Complex,运算符执行如下运算friend Complex operator +(Complex& a, Complex& b);//声明为该类的友元函数void print();private:double real;double imag;
};
例子
#include <iostream>
class Complex
{
public:Complex();~Complex();Complex(double r, double i);// Complex operator +(Complex&d);//重载运算符 相当于返回值类型为Complex类 当 Complex类 遇到加号 且后面为同类Complex,运算符执行如下运算friend Complex operator +(Complex& a, Complex& b);//声明为该类的友元函数void print();private:double real;double imag;
};Complex::Complex()
{
}Complex::~Complex()
{
}
Complex::Complex(double r, double i)
{real = r;imag = i;
}
Complex operator +(Complex &a, Complex &b)//在类中被声明了友元,所以可以访问私有;这同时是个运算符重载
{return Complex(a.real + b.real, a.imag + b.imag);//
}void Complex::print()
{std::cout << "(" << real << "," << imag << "i)";
}int main()
{Complex c1(1.0, 2.0), c2(3.0, -4.0), c3;c3 = c1 + c2;//该对象是Complex类遇到+,发生了重载,使用指定的运算int a, b=8, c=9;a = b + c;c3.print();std::cout << "Hello World!\n"<<a;
}
28再次重载<< (对数据流)
原理和26差不多,且用得不多;
29、多继承
当一个对象有多个身份的时候,就有了多种关系
一个人既可以是学生也可以是老师;基类是人,子类是老师、学生;还有一个子类既是学生也是老师;
因为多继承:所以可以访问不同父类的保护成员;
多继承的类声明
class 子类: public 父类, public 父类 //(class 子类:分号 public 父类, 逗号public 父类)
多继承的析构器
子类::子类析构(std::string N_name) : 分号 父类析构( N_name), 逗号 父类析构(N_name)
{
}
N_name为参数;
techer_student::techer_student(std::string N_name):techter( N_name), student(N_name)
{
}
例子
#include <iostream>
#include<string>
//*********************************************************************
class peson
{
public:peson(std::string N_name);protected:std::string name;
private:};peson::peson(std::string N_name)
{
}
//*******************************************************************************
class techter:public peson
{
public:techter(std::string N_name);
protected:std::string tech_banji="我作为老师,教大学三年级";private:};techter::techter(std::string N_name):peson(N_name)
{
}
//**********************************************************************************
class student:public peson
{
public:student(std::string N_name);
protected:std::string student_banji="我作为学生,在读清华博士";private:};student::student(std::string N_name):peson(N_name)
{
}
//******************************************************
class techer_student: public techter, public student
{
public:techer_student(std::string N_name);void jieshao();
protected:std::string techer_student_banji="我是学生也是老师";
private:};techer_student::techer_student(std::string N_name):techter( N_name), student(N_name)
{
}void techer_student::jieshao()
{std::cout << student::student_banji << '\n' << techter::tech_banji << '\n' << techer_student::techer_student_banji << '\n';//多继承 既可以使用student 的保护 也可以使用techter的保护
}int main()
{ techer_student lin("彭冠霖");lin.jieshao();std::cout << "Hello World!\n";
}
30、虚继承
虚继承的作用
虚继承的主要作用是解决多重继承中的“菱形继承”问题。在多重继承中,当一个类继承了多个父类,而这些父类又继承了同一个基类时,会导致子类中存在多份基类的拷贝,这会造成对基类成员的访问存在多义性
void techer_student::jieshao()
{std::cout << student::student_banji << '\n' << techter::tech_banji << '\n' << techer_student::techer_student_banji << '\n';techer_student::stud() ;//调用了名字techer_student::tech();调用了名字 本来就是同一个人,只能用同一个名字,在继承过来后应该统一名字//多继承 既可以使用student 的保护 也可以使用techter的保护
}
对基类成员的访问存在多义性
造成了继承了多个名字;
如下程序;
// ConsoleApplication1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//#include <iostream>
#include<string>
//*********************************************************************
class peson
{
public:peson(std::string N_name);protected:std::string name;
private:};peson::peson(std::string N_name)
{
}
//*******************************************************************************
class techter:public peson
{
public:techter(std::string N_name);
protected:std::string tech_banji="我作为老师,教大学三年级";void tech();
private:};techter::techter(std::string N_name):peson(N_name)
{name = N_name;
}
void techter::tech()
{std::cout << "我是" << name;
}
//**********************************************************************************
class student:public peson
{
public:student(std::string N_name);
protected:std::string student_banji="我作为学生,在读清华博士";void stud();
private:};student::student(std::string N_name):peson(N_name)
{name = N_name;
}
void student::stud()
{std::cout << "我是" << this->name;
}
//******************************************************
class techer_student: public techter, public student
{
public:techer_student(std::string N_name1, std::string N_name2);void jieshao();
protected:std::string techer_student_banji="我是学生也是老师";
private:};techer_student::techer_student(std::string N_name1,std::string N_name2):techter( N_name1), student(N_name2)
{
}void techer_student::jieshao()
{std::cout << student::student_banji << '\n' << techter::tech_banji << '\n' << techer_student::techer_student_banji << '\n';techer_student::stud() ;//调用了名字techer_student::tech();调用了名字 本来就是同一个人,只能用同一个名字,在继承过来后应该统一名字//多继承 既可以使用student 的保护 也可以使用techter的保护
}int main()
{ techer_student lin("彭冠霖","小彭");lin.jieshao();std::cout << "Hello World!\n";
}
虚继承,在每个继承的时候,在前面添加virtual
在子类的构造器添加基类继承 和父类
使用虚继承后的程序:和以上程序相比,没啥体现差别,除了关键字;
// ConsoleApplication1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//#include <iostream>
#include<string>
//*********************************************************************
class peson
{
public:peson(std::string N_name);protected:std::string name;
private:};peson::peson(std::string N_name)
{
}
//*******************************************************************************class techter: virtual public peson
{
public:techter(std::string N_name);
protected:std::string tech_banji="我作为老师,教大学三年级";void tech();
private:};techter::techter(std::string N_name):peson(N_name)
{name = N_name;
}
void techter::tech()
{std::cout << "我是" << name;
}
//**********************************************************************************
class student: virtual public peson
{
public:student(std::string N_name);
protected:std::string student_banji="我作为学生,在读清华博士";void stud();
private:};student::student(std::string N_name):peson(N_name)
{name = N_name;
}
void student::stud()
{std::cout << "我是" << this->name;
}
//******************************************************
class techer_student:virtual public techter, virtual public student
{
public:techer_student(std::string name);void jieshao();
protected:std::string techer_student_banji="我是学生也是老师";
private:};techer_student::techer_student(std::string name):techter(name), student(name),peson(name)
{
}void techer_student::jieshao()
{std::cout << student::student_banji << '\n' << techter::tech_banji << '\n' << techer_student::techer_student_banji << '\n';techer_student::stud() ;//调用了名字techer_student::tech();调用了名字 本来就是同一个人,只能用同一个名字,在继承过来后应该统一名字//多继承 既可以使用student 的保护 也可以使用techter的保护
}int main()
{ techer_student lin("彭冠霖");lin.jieshao();std::cout << "Hello World!\n";
}
再对比如下,效果一样;所以没体现出虚继承的差别;很疑惑
// ConsoleApplication1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//#include <iostream>
#include<string>
//*********************************************************************
class peson
{
public:peson(std::string N_name);protected:std::string name;
private:};peson::peson(std::string N_name)
{
}
//*******************************************************************************class techter: public peson
{
public:techter(std::string N_name);
protected:std::string tech_banji="我作为老师,教大学三年级";void tech();
private:};techter::techter(std::string N_name):peson(N_name)
{name = N_name;
}
void techter::tech()
{std::cout << "我是" << name;
}
//**********************************************************************************
class student: public peson
{
public:student(std::string N_name);
protected:std::string student_banji="我作为学生,在读清华博士";void stud();
private:};student::student(std::string N_name):peson(N_name)
{name = N_name;
}
void student::stud()
{std::cout << "我是" << this->name;
}
//******************************************************
class techer_student: public techter, public student
{
public:techer_student(std::string name);void jieshao();
protected:std::string techer_student_banji="我是学生也是老师";
private:};techer_student::techer_student(std::string name):techter(name), student(name)//,peson(name)
{
}void techer_student::jieshao()
{std::cout << student::student_banji << '\n' << techter::tech_banji << '\n' << techer_student::techer_student_banji << '\n';techer_student::stud() ;//调用了名字techer_student::tech();调用了名字 本来就是同一个人,只能用同一个名字,在继承过来后应该统一名字//多继承 既可以使用student 的保护 也可以使用techter的保护
}int main()
{ techer_student lin("彭冠霖");lin.jieshao();std::cout << "Hello World!\n";
}
31、32错误处理和调试
错误分为编译错误和运行错误
编译时错误
经验:
- 在编程的时候保持一种风格、一旦决定要如何命名变量和函数、如何缩进、何种格式编写代码;
- 认真对待编译器的错误和警告
- 先画流程图
- 编译错误、先完整的看一遍代码、再矫正错误;
- 注意基本语法
- 把可能有问题的代码注释掉
- 换一个环境或者开发工具:可能是杀毒软件,什么之类的影响;
- 头文件包含
- 留意变量的作用域和命名空间
- 休息一下:效率下降后需要休息;
- 多使用调试工具
- 把调试好的程序控制保存起来;把代码划分成模块,来搭建新程序可以减少很多时间;
运行时的错误
逻辑漏洞;bug同一个产品一个好一个坏;时有时无没法确定;
经验;
- 保持一种良好的编程风格
- 多注释,注释好,特别是参数变化;简单代码,不要啰嗦
- 操作符优先级,括号很保险
- 输入输出合法性检查
- 不要做任何假设:用户不会按照你的想法去使用你的程序;
- 划分单元模块,这样测试方便
让函数返回错误代码
输入输出错误码
使用climits头文件
给定操作系统上的取值范围:每种数据的上下限给我们使用
如:SHORT_MAX 、SHORT_MIN分别代表短整类型的最大取值和最小取值;
例子:使用使用climits头文件
#include <iostream>
#include<climits>//引用c限制头文件
class ftory
{
public:ftory(unsigned short num);~ftory();unsigned long get_ftory();bool inRange();private:unsigned short number;
};ftory::ftory(unsigned short num)
{this->number = num;std::cout << "输入参数为" << this->number<<'\n';
}ftory::~ftory()
{
}
unsigned long ftory::get_ftory()
{unsigned long sun = 1;for (int i=1;i<= number;i++){sun *= i;}return sun;
}
bool ftory::inRange()
{unsigned long temp= ftory::get_ftory();if (temp >= USHRT_MAX )//这是climit头文件里面的限制参数return false; //超出限制就返回falseelsereturn true;
}int main()
{ftory a(20);std::cout<< a.get_ftory()<<'\n';std::cout << a.inRange() << '\n';std::cout << "Hello World!\n";
}
33、运行错误、异常捕获
#include<cassert>//前面的c表示时c库里面的
assert(条件判断);条件不成立时,提示错误,可以用这个函数定位运行错误
输出窗口可以定位文件和行数
#include <iostream>
#include<cassert>int main()
{uint16_t i;std::cin >> i;assert(i<100);std::cout << "Hello World!\n";
}
#include
捕获异常
运行错误分为两种
- 开发 调试 测试过程中,尽可能的查找和定位错误;使用函数assert等等;
- 和最终用户有关,尽可能的把用户感受放第一位;用户不懂技术,要用户能轻松使用;输出也不能全部开放,看不懂只会增加用户麻烦;
大公司微软都不可能没有bug,关键在于后续升级
捕获异常:
为了对付潜在的编程错误。异常:就是与期望不相符合的反常现象
捕获异常的的基本使用思路
- 安排c++代码去尝试某件事 (try 语句)
- 如果发生问题就抛出一个异常
- 再安排一些代码捕获这个异常并进行相应的处理(catch语句)
Try 至少配一条 catch语句,否则中止程序
Catch (int a) {.........}//捕获int型
Catch (bool) {.........}//捕boolt型
Catch (char) {.........}
//Catch 可以捕获任何类型的
C++ 中Exception 的文件 声明exception 的基类。可以用这个基类来做私人的子类作为异常管理
可以抛出和捕获exception 类或者子类的对象:以值传递抛出,以引用方式捕获;
在抛出异常的方法添加throw (抛出异常类型指针)
bool ftory::inRange()throw (const char *)
{}
try{
可以抛出异常的方法调用
}
catch (抛出的异常类型)//对应异常的catch (指定为 const char* 类型)
{
std::cout << e;//输出异常
}
例子
#include<exception>//异常头文件 没体现出来
#include <iostream>
#include<climits>//引用c限制头文件
class ftory
{
public:ftory(unsigned short num);~ftory();unsigned long get_ftory();bool inRange();private:unsigned short number;
};ftory::ftory(unsigned short num)
{this->number = num;std::cout << "输入参数为" << this->number << '\n';
}ftory::~ftory()
{
}
unsigned long ftory::get_ftory()
{unsigned long sun = 1;for (int i = 1; i <= number; i++){sun *= i;}return sun;
}
bool ftory::inRange()throw (const char *)//能抛出异常的方法定义
{unsigned long temp = ftory::get_ftory();if (temp >= USHRT_MAX){//这是climit头文件里面的限制参数throw "数值太大了 抛出了一个字符异常 ";//抛出异常 为const char *类型return false; //超出限制就返回false}else{return true;}
}int main()
{ftory a(20);std::cout << a.get_ftory() << '\n';try {//可能会抛出异常额函数std::cout << a.inRange() << '\n';}catch (const char* e)//对应异常的catch (指定为 const char* 类型){std::cout << e;}std::cout << "Hello World!\n";
}
34动态内存管理
静态内存,结构体、变量、数组 静态内存,固定占用固定大小的内存
动态内存:由一些没有名字、只有地址的内存块构成,那些内存块是在程序运行期间动态分配;
由new 申请内存返回地址;
1、如inte *p =new int;申请了int类型大小的内存,并且返回内存起始地址
2、没有足够的内存空间,new语句抛出异常std::bad_alloc异常;
3、用完内存之后要用delete释放内存;且将指针设置为null;没有释放就是bug;
4、new 出来的内存要先使用填充数据,再访问读取;或者构造器里面直接先初始化
关于这个p=null 使用这个p无法访问,否则访问就程序中止;
int *p =new int;delete p;p=null;
35动态数组
int a = 10;int* p = new int[a];//建立动态数组delete []p;//删除数组
delete []p;//删除数组 方括号+数组的指针
相关文章:
c++笔记2
14、c的对象 对象和结构的区别; 结构:包含各种类型的变量; 对象:包含各种函数、和变量; 设计对象的时候引用class关键字创建类,和结构形状差不多; 将变量称之为属性,函数称之为方…...
Xlsxwriter生成Excel文件时TypeError异常处理
在使用 XlsxWriter 生成 Excel 文件时,如果遇到 TypeError,通常是因为尝试写入的值或格式与 XlsxWriter 的限制或要求不兼容。 1、问题背景 在使用 Xlsxwriter 库生成 Excel 文件时,出现 TypeError: “expected string or buffer” 异常。此…...
应用层协议/传输层协议(UDP)
目录 应用层 如何自定义应用层协议? 序列化方式 1.基于行文本的方式来传输 2.基于xml的方式 3.基于json的方式 4.yml的形式 5.protobuffer(pb)形式 传输层 端口号 协议 UDP 校验和 CRC TCP TCP/IP五层协议 应用层 -- 传输层 -- 网络层 -- 数据链路层…...
【Linux】应用层协议—HTTP
一、HTTP协议介绍 请求-响应模型:HTTP (Hyper Text Transfer Protocol) 协议是基于请求和响应的。客户端(如Web浏览器)发送一个HTTP请求到服务器,服务器处理请求后返回一个HTTP响应。 无状态,无连接协议:H…...
使用Vue3+Echarts实现加载中国地图,点击省份地图下钻(完整教程)
一. 前言 在众多 ECharts 图表类型中,开发者始终绕不开的有各种各样的地图开发,关于地图开发,可能比其他图表相对繁琐一些,其实说简单也简单,说复杂也复杂,其中不乏有层级地图、3D 地图等,感觉…...
双目相机的标定,视差图,深度图,点云生成思路与实现。
该文档记录从双目相机标定到点云生成的所有过程,同时会附上代码。 代码直接能跑。https://github.com/stu-yzZ/stereoCamera 目录 大致思路如下: 一、相机标定 1、相机参数介绍 2、单目相机标定 3、双目相机标定 二、图片畸变矫正 三、极线矫正…...
解决 minio上传文件Service: S3, Status Code: 403
错误信息 [software.amazon.awssdk.services.s3.model.S3Exception: (Service: S3, Status Code: 403, Request ID: 180E9BC04F11312E, Extended Request ID: 81aefed089495c5faf6270c59bea93c9783926f74ef647fe6b17908f0976b557)]分析过程 4XX一般是客户端错误。403表示禁止…...
SpringBoot实战——个人博客项目
目录 一、项目简介 ?二、项目整体架构 数据库模块 后端模块 前端模块 ?三、项目具体展示 ?四、项目的具体实现 1、一些准备工作 ??数据库、数据表的创建 ??设置数据库和MyBatis的配置 ??将前端项目引入到当前项目中 2、登录注册模块 ??实体类的创建 ?…...
OpenCV-平滑图像
二维卷积(图像滤波) 与一维信号一样,图像也可以通过各种低通滤波器(LPF)、高通滤波器(HPF)等进行过滤。LPF 有助于消除噪音、模糊图像等。HPF 滤波器有助于在图像中找到边缘。 opencv 提供了函数 **cv.filter2D()**&…...
nodejs官方文档学习-笔记-1
一、异步工作 process.nextTick(): 回调会在当前操作完成后立即执行,但在事件循环进入下一个阶段之前。它是最先执行的。 Promise.then(): 回调会在 microtask 队列中执行,通常是在当前操作完成后,但在事件循环进入…...
YOLOv7
YOLOv7 是 YOLO 系列的一个重要版本,由 Chien-Yao Wang 和 Alexey Bochkovskiy 等研究人员和开发者提出,继续改进了 YOLOv4 和 YOLOv5 的设计,主要在模型性能、训练效率以及推理速度上进行优化。YOLOv7 进一步优化了 YOLO 系列在速度和精度之…...
汉语唤醒词的模糊判断(Python)
汉语唤醒词的模糊判断【Python】 说明安装库代码Demo其他 说明 这是一个简单的汉语模糊唤醒词的判断器,汉语发音中前后舌以及声母韵母的区别,如果进行精准判断,很容易误判。需要一个模糊判断的逻辑! 安装库 pip install pypinyin代码Demo …...
C语言实例_26之根据输入计算星期几
1. 问题 请输入星期几的第一个字母来判断一下是星期几,如果第一个字母一样,则继续判断第二个字母。 2. 实现思路 思路一:嵌套if-else语句实现 首先接收用户输入的第一个字母,使用if-else语句进行判断。如果输入的是M࿰…...
包管理器npm,cnpm,yarn和pnpm
npm (Node Package Manager) 核心技术与工作原理 依赖解析: 广度优先搜索(BFS):npm 使用 BFS 算法来解析依赖树,尽量扁平化 node_modules 目录以减少重复的依赖项。冲突处理:如果两个包需要同一个依赖的不…...
docker-compose部署skywalking 8.1.0
一、下载镜像 #注意 skywalking-oap-server和skywalking java agent版本强关联,版本需要保持一致性 docker pull elasticsearch:7.9.0 docker pull apache/skywalking-oap-server:8.1.0-es7 docker pull apache/skywalking-ui:8.1.0二、部署文件docker-compose.yam…...
Android -- [SelfView] 自定义多行歌词滚动显示器
Android – [SelfView] 自定义多行歌词滚动显示器 流畅、丝滑的滚动歌词控件* 1. 背景透明;* 2. 外部可控制进度变化;* 3. 支持屏幕拖动调节进度(回调给外部);效果 歌词文件(.lrc) 一. 使用…...
记事本建java及java命名规范
1.桌面开发:c# 2. 记事本建java: 以class的名称(类名)为名,名称.java 编译jdk:javac 名称.java 调动运行jre : java 名称 查看名称.java里面的内容:cat 名称.java java 的命名规范 大驼峰(每个单词首…...
Elasticsearch scroll 之滚动查询
Elasticsearch scroll 之滚动查询 Elasticsearch 的 Scroll API 是一种用于处理大规模数据集的机制,特别是在需要从索引中检索大量数据时。通常情况下,Elasticsearch 的搜索请求会有一个结果集大小的限制 (fromsize 的检索数量默认是 10,000 条记录)&am…...
cartographer建图与定位应用
文章目录 前言一、安装cartographer1.安装环境2.源码编译2.1 下载2.2 编译 二、gazebo仿真2d建图0.准备仿真环境1.编写lua文件2.编写启动文件3.建图保存 三、cartographer定位 move_base导航3.1 编写启动文件3.2 启动launch 总结 前言 本文介绍cartographer在ubuntu18.04下的…...
CEEMDAN-CPO-VMD二次分解(CEEMDAN+冠豪猪优化算法CPO优化VMD)
CEEMDAN-CPO-VMD二次分解(CEEMDAN冠豪猪优化算法CPO优化VMD) 目录 CEEMDAN-CPO-VMD二次分解(CEEMDAN冠豪猪优化算法CPO优化VMD)效果一览基本介绍程序设计参考资料 效果一览 基本介绍 首先运用CEEMDAN对数据进行一次分解ÿ…...
【Golang】Go语言编程思想(二):函数式编程
函数式编程 函数与闭包 支持函数式编程的语言当中,函数是一等公民,参数、变量、返回值都可以是函数。 以 adder 为例,下例实现了一个函数式编程: package mainimport "fmt"func adder() func(int) int {sum : 0retu…...
ros项目dual_arm_pick-place(moveit和gazebo联合仿真)(一)
目录 前言正文创建功能包具体代码运行 总结 前言 dual_arm_pick-place项目中,实现了两套的moveit和gazebo联合仿真。 启动文件分别是bringup_moveit.launch和arm_bringup_moveit.launch。 在这个项目中,我将代码重新创建了一个包,co_simula…...
点线面|点到两点直线距离求解
在点云库(PCL)中,计算点到直线的距离可以借助于向量运算。以下是这种计算方法的步骤以及相应的实现代码。 概念 要计算点 AA 到通过点 BB 和 CC 定义的直线的距离,可以使用以下步骤: 定义两个向量: 向量 …...
等保2.0三级测评华为华三交换机路由器
在使用本博客提供的学习笔记及相关内容时,请注意以下免责声明: 信息准确性:本博客的内容是基于作者的个人理解和经验,尽力确保信息的准确性和时效性,但不保证所有信息都完全正确或最新。 非专业建议:博客中的内容仅供参考,不能替代专业人士的意见和建议。在做出任何重要…...
鸿蒙分享(二):引入zrouter路由跳转+封装
码仓库:https://gitee.com/linguanzhong/share_harmonyos 鸿蒙api:12 鸿蒙第三方库地址:OpenHarmony三方库中心仓 zrouter地址:OpenHarmony三方库中心仓 1.引入zrouter 1.打开终端界面:输入 ohpm install hzw/zrouter 2.在项目…...
欧拉角和旋转矩阵之间的转换
在实际编程实践中,特别是使用C的Eigen库时,需要掌握多种空间旋转表示之间的转换。本文将深入探讨欧拉角与旋转矩阵之间的相互转换,这是使用库时常见的操作。 首先,让我们了解欧拉角。它是指通过围绕三个基本坐标轴旋转来表示三维对…...
Typora的激活
Typora的安装、激活 图文教程 | 2024年最新Typora激活使用教程合集 Typora 激活指南(2024年最新版) 图文教程 | 2024Typora最新版免费激活使用教程(新旧版可用)...
排查bug的通用思路
⭐️前言⭐️ APP点击某个按钮没有反应/PC端执行某个操作后,响应较慢,通用的问题排查方法: 从多个角度来排查问题 🍉欢迎点赞 👍 收藏 ⭐留言评论 🍉博主将持续更新学习记录收获,友友们有任何问题可以在评…...
探秘CSS3 3D转换:打造立体网页动画与视觉效果的魔法
在现代网页设计中,CSS3 3D转换(3D Transforms)已经成为一种强大的工具,用于创建各种动态效果和视觉吸引力。本文将详细介绍CSS3 3D转换的基本概念、常见属性及其应用示例,帮助您掌握这一技术,提升网页设计的…...
Pycharm 安装两种不同版本的解释器
背景 Pycharm使用的解释器是python3.11,python3.9.x之后不支持win7;有同事需要在win7上使用python制作的exe,而了“win7环境下运行python打包exe提示找不到api-ms-win-core-path-l1-1-0.dll”。 过程 查找了一些资料,发现直接将…...
小红薯x-s算法分析最新12-06(x-s 56)(上)
目标-小红薯达人作品:aHR0cHM6Ly93d3cueGlhb2hvbmdzaHUuY29tLw 1、确定目标 打上xhr断点 发现是异步请求,同时各个参数已经生成结束了 2、进入第二个异步函数 打上断点并继续运行 发现在e这个位置也生成了,那么再继续往上找异步参数进行断…...
视频融合×室内定位×数字孪生
随着物联网技术的迅猛发展,室内定位与视频融合技术在各行各业中得到了广泛应用。不仅能够提供精确的位置信息,还能通过实时视频监控实现全方位数据的可视化。 与此同时,数字孪生等技术的兴起为智慧城市、智慧工厂等应用提供了强大支持&#…...
JMS和消息中间件:Kafka/RocketMQ
文章目录 消息传递模型使用JMS还是KafkaKafka与RocketMQ的优缺点Kafka与RocketMQ的使用场景Kafka与RocketMQ的选型指南 TPM 项目中, iflow之间使用了JMS,后端项目与数据库通信使用Kafka MQ和JMS的区别: JMS是 java 用来处理消息的一个API规范…...
FreeRTOS之ARM CR5栈结构操作示意图
FreeRTOS之ARM CR5栈结构操作示意图 1 FreeRTOS源码下载地址2 ARM CR5栈结构操作宏和接口2.1 portSAVE_CONTEXT宏2.1.1 portSAVE_CONTEXT源码2.1.2 portSAVE_CONTEXT宏操作栈结构变化示意图 2.2 portRESTORE_CONTEXT宏2.2.1 portRESTORE_CONTEXT源码2.2.2 portRESTORE_CONTEXT宏…...
【技巧】Mac上如何显示键盘和鼠标操作
在制作视频教程时,将键盘和鼠标的操作在屏幕上显示出来,会帮助观众更容易地理解。 推荐Mac上两款开源的小软件。 1. KeyCastr 这款工具从2009年至今一直在更新中。 https://github.com/keycastr/keycastr 安装的话,可以从Github上下载最…...
三种插入排序算法
目录 1.直接插入排序 直接插入排序的步骤示例 直接插入排序的特点 适用场景 2.折半插入排序 折半插入排序的基本原理 折半插入排序的实现过程 折半插入排序的时间复杂度 折半插入排序的特点 3.希尔排序 希尔排序的基本原理 希尔排序的步骤举例 希尔排序的时间复杂…...
力扣100题--移动零
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。 请注意 ,必须在不复制数组的情况下原地对数组进行操作。 示例 1: 输入: nums [0,1,0,3,12] 输出: [1,3,12,0,0]示例 2: 输入: nums [0] 输出: […...
第30天:安全开发-JS 应用NodeJS 指南原型链污染Express 框架功能实现审计0
时间轴: 演示案例: 环境搭建-NodeJS-解析安装&库安装 功能实现-NodeJS-数据库&文件&执行 安全问题-NodeJS-注入&RCE&原型链 案例分析-NodeJS-CTF 题目&源码审计 开发指南-NodeJS-安全 SecGuide 项目、 环境搭建-NodeJ…...
1.使用docker 部署redis Cluster模式 集群3主3从
1.使用docker 部署redis Cluster模式 集群3主3从 1.1 先安装docker 启动docker服务,拉取redis镜像 3主3从我们要在docker启动6个容器docker run --name redis-node-1 --net host --privilegedtrue -v /data/redis/share/redis-node-1:/data redis:6.0.8 --cluster-…...
SAP导出表结构并保存到Excel 源码程序
SAP导出表结构并保存到Excel,方便写代码时复制粘贴 经常做接口,需要copy表结构,找到了这样一个程程,特别有用。 01. 先看结果...
李飞飞:Agent AI 多模态交互的前沿探索
发布于:2024 年 11 月 27 日 星期三 北京 #RAG #李飞飞 #Agent #多模态 #大模型 Agent AI在多模态交互方面展现出巨大潜力,通过整合各类技术,在游戏、机器人、医疗等领域广泛应用。如游戏中优化NPC行为,机器人领域实现多模态操作等。然而,其面临数据隐私、偏见、可解释性…...
算法基础学习Day2(双指针)
文章目录 1.题目2.题目解答1.快乐数题目及题目解析算法学习代码提交 2.题目2题目及题目解析算法学习代码提交 1.题目 202. 快乐数 - 力扣(LeetCode)11. 盛最多水的容器 - 力扣(LeetCode) 2.题目解答 1.快乐数 题目及题目解析 …...
信奥常考点:二叉树的构建(已知中序和 前序或后序 的情况下)
一、题目引入 这是来自CCF-GESP C七级认证 2024年9月的题目。 我们在此不解题,只把树画出来。 CCF-GESP 编程能力认证 C 七级 2024年9月份详细解析-CSDN博客 二、解题过程 我们可以根据先序遍历得出根节点是A,然后我们得到了A的左子树[B D](橙…...
《CS2》运行时提示“缺少steam_api_64.dll”文件该如何处理?“找不到steam_api.dll,无法继续执行代码”的修复方法
《CS2》游戏运行时文件丢失、损坏与系统报错处理指南 《CS2》上海 Major 淘汰赛这两天也在如火如荼的进行当中,相信有很多go学长在游戏运行时会遇到各种文件丢失、损坏以及系统报错问题,给玩家带来极大的困扰。今天,我们就来详细探讨一下《C…...
MCPTT 与BTC
MCPTT(Mission Critical Push-to-Talk)和B-TrunC(宽带集群)是两种关键通信标准,它们分别由不同的组织制定和推广。 MCPTT(Mission Critical Push-to-Talk)标准由3GPP(第三代合作伙伴…...
aardio - 汉字笔顺处理 - json转sqlite转png
本代码需要最新版 godking.conn 库,请自行下载! 如果没有安装 odbc for sqlite 驱动,可以使用 godking.conn.driver.sqlite3.install() 安装。 也可以在此下载自行安装:http://www.chengxu.online/show.asp?softid267 1、将js…...
图的遍历之DFS邻接矩阵法
本题要求实现一个函数,对给定的用邻接矩阵存储的无向无权图,以及一个顶点的编号v,打印以v为起点的一个深度优先搜索序列。 当搜索路径不唯一时,总是选取编号较小的邻接点。 本题保证输入的数据(顶点数量、起点的编号等…...
kdenlive 一个视频一左一右拼接(抖音长屏转宽屏)
参考kdenlive 剪裁_Kdenlive中的分层合成-CSDN博客 kdenlive 一个视频一左一右拼接(抖音长屏转宽屏) 按照图片的操作...
深度学习-53-AI应用实战之基于labelImg和labelme的手动标注
文章目录 1 labelImg1.1 简介1.2 安装使用1.3 文件格式1.3.1 pascalVOC格式1.3.2 yolo格式1.4 验证显示2 labelme2.1 简介2.2 安装使用2.3 labelme转换为yolo3 参考附录1 labelImg 1.1 简介 labelImg(label image)是一个开源的图像标注工具,用于创建图像标注数据集。它提供了…...
白鲸优化算法原理,白鲸算法公式,白鲸算法应用(白鲸算法测试效果,白鲸算法优化BP神经网络,白鲸算法路径优化)
目录 白鲸算法主要原理 白鲸算法主要公式 白鲸算法应用案例 白鲸算法主要原理 白鲸优化算法(Beluga Whale Optimization Algorithm,BWO)是一种基于种群的元启发式优化算法,灵感来源于白鲸的生活行为。该算法通过模拟白鲸的游泳、捕食和鲸落行为来实现模型参数的优化…...