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子类的构造器和析构

创建对象时:

先执行父类的构造器

才到子类的构造器;

销毁对象时:

子类的最后一条语句结束后调用基类的析构器;

  1. 首先调用子类的析构器。
  2. 然后调用父类的析构器。

带参数的构造器声明

父类,基类

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错误处理和调试

错误分为编译错误和运行错误

编译时错误

经验:

  1. 在编程的时候保持一种风格、一旦决定要如何命名变量和函数、如何缩进、何种格式编写代码;
  2.   认真对待编译器的错误和警告
  3. 先画流程图
  4. 编译错误、先完整的看一遍代码、再矫正错误;
  5. 注意基本语法
  6. 把可能有问题的代码注释掉
  7. 换一个环境或者开发工具:可能是杀毒软件,什么之类的影响;
  8. 头文件包含
  9. 留意变量的作用域和命名空间
  10. 休息一下:效率下降后需要休息;
  11. 多使用调试工具
  12. 把调试好的程序控制保存起来;把代码划分成模块,来搭建新程序可以减少很多时间;

运行时的错误

逻辑漏洞;bug同一个产品一个好一个坏;时有时无没法确定;

经验;

  1. 保持一种良好的编程风格
  2. 多注释,注释好,特别是参数变化;简单代码,不要啰嗦
  3. 操作符优先级,括号很保险
  4. 输入输出合法性检查
  5. 不要做任何假设:用户不会按照你的想法去使用你的程序;
  6. 划分单元模块,这样测试方便

让函数返回错误代码

输入输出错误码

使用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

捕获异常

运行错误分为两种

  1. 开发 调试 测试过程中,尽可能的查找和定位错误;使用函数assert等等;
  2. 和最终用户有关,尽可能的把用户感受放第一位;用户不懂技术,要用户能轻松使用;输出也不能全部开放,看不懂只会增加用户麻烦;

大公司微软都不可能没有bug,关键在于后续升级

捕获异常:

为了对付潜在的编程错误。异常:就是与期望不相符合的反常现象

捕获异常的的基本使用思路

  1. 安排c++代码去尝试某件事 (try 语句)
  2. 如果发生问题就抛出一个异常
  3. 再安排一些代码捕获这个异常并进行相应的处理(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;//删除数组  方括号+数组的指针

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/485903.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

停止等待协议

理想传输条件有以下两个特点&#xff1a; 传输信道不产生差错不管发送发以多快的速度发送数据&#xff0c;接收方总是来得及处理收到的数据。 然而实际的网络都不具备以上两个理想条件&#xff0c;所以需要一个协议 “停止等待协议”就是每发送完一个分组就停止发送&#xf…

python | print() 函数常被忽略的几点用法

在 python 编程中&#xff0c;print() 是最为基础和常用的函数。 也正因如此&#xff0c;print() 函数的一些基础用法常常被我们初学者所忽略&#xff0c;典型的有&#xff1a;换行问题、间隔符使用及格式化输出等。 一、print() 换行问题 1、默认情况下&#xff0c;每一个 …

《鸣潮》运行时电脑提示“d3dx9_41.dll丢失”是什么原因?“缺失d3dx9_41.dll文件”的解决方法和预防方案

游戏运行时文件丢失与报错解决方案&#xff1a;《鸣潮》提示“d3dx9_41.dll丢失”怎么办&#xff1f; 大家好&#xff0c;我是一名在软件开发领域有着丰富经验的从业者。在游戏爱好者的世界里&#xff0c;遇到游戏运行时提示文件丢失或损坏的情况并不少见。今天&#xff0c;我…

性能测试需求分析(超详细总结)

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 1、客户方提出 客户方能提出明确的性能需求&#xff0c;说明对方很重视性能测试&#xff0c;这样的企业一般是金融、电信、银行、医疗器械等&#xff1b;他们…

(长期更新)《零基础入门 ArcGIS(ArcMap) 》实验三----学校选址与路径规划(超超超详细!!!)

目录 实验三 学校选址与道路规划 3.1 实验内容及目的 3.1.1 实验内容 3.1.2 实验目的 3.2 实验方案 3.3 操作流程 3.3.1 环境设置 3.3.2 地势分析 &#xff08;1&#xff09;提取坡度: (2)重分类: 3.3.3 学校点分析 (1)欧氏距离: (2)重分类: 3.3.4 娱乐场所点分析 (1)欧氏距离…

计算机网络 —— HTTPS 协议

前一篇文章&#xff1a;计算机网络 —— HTTP 协议&#xff08;详解&#xff09;-CSDN博客 目录 前言 一、HTTPS 协议简介 二、HTTPS 工作过程 1.对称加密 2.非对称加密 3.中间人攻击 4.引入证书 三、HTTPS 常见问题 1.中间人能否篡改证书&#xff1f; 2.中间人能否调…

【调试工具】USB 转 UART 适配器(USB 转 TTL)

「USB 转 TTL 转换器」是错误的叫法&#xff0c;正确的叫法应该为 「USB 转 UART 适配器」。 Device connection 注意端口的交叉连接&#xff0c;Device1_TX<---->Device2_RX USB-to-UART adapter GND 记得接地。 使用&#xff1a; 当 TX,RX 需要电平为 0-3.3V 时&am…

116. UE5 GAS RPG 实现击杀掉落战利品功能

这一篇&#xff0c;我们实现敌人被击败后&#xff0c;掉落战利品的功能。首先&#xff0c;我们将创建一个新的结构体&#xff0c;用于定义掉落体的内容&#xff0c;方便我们设置掉落物。然后&#xff0c;我们实现敌人死亡时的掉落函数&#xff0c;并在蓝图里实现对应的逻辑&…

图像生成-扩散模型的经典之作DDPM

论文&#xff1a;https://arxiv.org/pdf/2006.11239 项目&#xff1a;https://github.com/hojonathanho/diffusion Denoising Diffusion Probabilistic Models (DDPM) 是一种生成模型&#xff0c;它通过一系列逐步添加噪声的过程将数据点映射到一个简单的先验分布&#xff08;…

【Axure视频教程】中继器表格——筛选后的条件判断

今天教大家在Axure制作中继器表格筛选以及筛选后条件交互的原型模板&#xff0c;我们可以在输入框里输入员工姓名&#xff0c;点击查询按钮后可以筛选出对应的数据&#xff0c;筛选后会进行条件判断&#xff0c;如果筛选不到任何数据&#xff0c;就会显示提示弹窗。这个原型模板…

GDPU 人工智能 期末复习

1、python基础 2、回归、KNN、K-Means、搜索方法思想及算法实现步骤 3、知识表示基本概念 4、状态空间的相关概念、表示方法及应用 5、图搜索策略及应用 6、问题归约概念、与或图搜索、博弈树搜索与剪枝 7、决策树、贝叶斯决策算法及其应用 8、神经网络与深度学习基本概念 一、…

几个Linux系统安装体验: 龙蜥服务器系统

本文介绍龙蜥服务器系统&#xff08;AnolisOS&#xff09;的安装。 下载 下载地址&#xff1a; https://openanolis.cn/download 选定版本为8.6。 本文下载的文件名称为AnolisOS-8.6-x86_64-minimal.iso&#xff0c;体积约2.2GB。另&#xff1a;AnolisOS-8.6-QU1-x86_64-dv…

Unity 设计模式-策略模式(Strategy Pattern)详解

策略模式&#xff08;Strategy Pattern&#xff09;是一种行为型设计模式&#xff0c;定义了一系列算法&#xff0c;并将每种算法封装到独立的类中&#xff0c;使得它们可以互相替换。策略模式让算法可以在不影响客户端的情况下独立变化&#xff0c;客户端通过与这些策略对象进…

阿拉丁论文助手:一键点亮学术之路

在学术研究的海洋中&#xff0c;每一位学者都渴望拥有一盏能够照亮前行道路的神灯。阿拉丁论文助手&#xff0c;正是这样一盏神奇的灯&#xff0c;它以其先进的人工智能技术和丰富的学术资源&#xff0c;为学者们的学术写作提供了全方位的支持。 一、阿拉丁论文助手简介 阿拉丁…

YOLOv10改进,YOLOv10添加U-Netv2分割网络中SDI信息融合模块,助力小目标检测

摘要 理论介绍 SDI模块的架构: 平滑卷积(SmoothConv):用于平滑特征图,帮助减少噪声并使得特征更加稳定。Hadamard积:用于在特征图中进行逐元素相乘(点乘),以加强语义信息和细节信息的融合。通道注意力(ChannelAttention):利用通道注意力机制来自动关注重要的特征通…

解锁 AI 潜能 - ChatGPT等大模型提示词技巧

在人工智能领域&#xff0c;ChatGPT 等大语言模型正在重新定义我们的工作和生活方式。这些强大的 AI 大模型 能够理解自然语言并生成高质量的内容&#xff0c;无论是撰写文案、解决问题&#xff0c;还是数据分析&#xff0c;都展现了卓越的表现。如何高效使用这些工具&#xff…

基于Java和Vue开发的漫画阅读软件漫画阅读小程序漫画APP

前景分析 受众广泛&#xff1a;漫画的受众群体广泛&#xff0c;不仅限于青少年&#xff0c;还涵盖了成年人等多个年龄层和社会阶层。漫画文化在全球范围内的影响力不断扩大&#xff0c;未来漫画软件创业可以考虑全球市场的拓展。 市场需求大&#xff1a;数字化阅读趋势下&…

GEE:CCDC 分类组件,对每个分段进行分类

作者:CSDN @ _养乐多_ 连续变化检测与分类(Continuous Change Detection and Classification, CCDC) 利用了时间序列拟合来对影像中的像素值随时间的变化趋势建模。每一段模型代表一个时间段内的地表覆盖类型和状态。 本文将解释如何在谷歌地球引擎(Google Earth Engine,…

vue3+elementPlus封装的一体表格

目录结构 源码 exportOptions.js export default reactive([{label: 导出本页,key: 1,},{label: 导出全部,key: 2,}, ])index.vue <template><div class"flex flex-justify-between flex-items-end"><div><el-button-group><slot name…

【计算机组成原理】CPU概述

文章目录 CPU主要功能CPU总体结构模型运算部件缓存部件寄存器组(堆)控制器时序部件 CPU主要功能 CPU是取指令并执行指令的部件 CPU总体结构模型 运算部件 运算部件用于对操作数进行运算&#xff0c;主要是算术运算/逻辑运算 运算部件的基本组成如下&#xff1a; 缓存部件 缓…