
C++/类、对象
文章平均质量分 67
C++/类、对象
u013250861
这个作者很懒,什么都没留下…
展开
-
C++-STL:STL概论
STL提供了六大组件,彼此之间可以组合套用,这六大组件分别是:容器、算法、迭代器、仿函数、适配器(配接器)、空间配置器。容器:各种数据结构,如vector、list、deque、set、map等,用来存放数据,从实现角度来看,STL容器是一种class template。算法:各种常用的算法,如sort、find、copy、for_each。原创 2024-07-22 00:07:18 · 900 阅读 · 0 评论 -
C++-文件读写:
2) 每一个打开的文件都有一个文件指针,该指针的初始位置由I/O方式指定,每次读写都从文件指针的当前位置开始。当文件指针移到最后,就会遇到文件结束EOF(文件结束符也占一个字节,其值为-1),此时流对象的成员函数eof的值为非0值(一般设为1),表示文件结束 了。4) 如果打开操作失败,open函数的返回值为0(假),如果是用调用构造函数的方式打开文件的,则流对象的值为0。ios::app | ios::nocreate //打开一个输出文件,在文件尾接着写数据,若文件不存在,则返回打开失败的信息。转载 2024-07-22 00:07:08 · 968 阅读 · 0 评论 -
C++-类-多态7:指向类成员的指针
返回类型>(::*)() = &::例如: void (A::pFunc)(int,int) = &A::func;数据类型> ::* = &::(->*)()返回类型> (::*)()(.*)()类对象指针>->*数据类型> ::*原创 2024-07-22 00:06:51 · 669 阅读 · 0 评论 -
C++-类-多态6:重写、重载、重定义
const也可以作为重载条件 //do(const Teacher& t){} do(Teacher& t)子类(派生类)重新定义父类(基类)的同名成员(非virtual函数)函数返回值,函数名字,函数参数,必须和基类中的虚函数一致。子类(派生类)重写父类(基类)的virtual函数。重定义基类的func2,隐藏了基类的func2方法。重写基类的func3函数,也可以覆盖基类func3。参数个数,参数顺序,参数类型不同。同一作用域下,func1函数重载。重载,同一作用域的同名函数。原创 2024-07-22 00:06:43 · 229 阅读 · 0 评论 -
C++-类-多态6:虚析构函数
纯虚析构函数在c++中是合法的,但是在使用的时候有一个额外的限制:必须为纯虚析构函数提供一个函数体。如果类的目的不是为了实现多态,作为基类来使用,就不要声明虚析构函数,反之,则应该为类声明虚析构函数。纯虚析构函数和非纯析构函数之间唯一的不同之处在于纯虚析构函数使得基类是抽象类,不能创建基类的对象。那么问题是:如果给虚析构函数提供函数体了,那怎么还能称作纯虚析构函数呢?指向派生类对象,并用基类的指针删除派生类对象。类是抽象类,不可以实例化对象。析构函数 People!析构函数 Worker!原创 2024-07-22 00:06:34 · 427 阅读 · 0 评论 -
C++-类-多态5:纯虚函数和多继承【c++中没有接口的概念,但是可以通过纯虚函数实现接口】【 接口类中只有函数原型定义,没有任何数据定义】
绝大数面向对象语言都不支持多继承,但是绝大数面向对象对象语言都支持接口的概念,c++中没有接口的概念,但是可以通过纯虚函数实现接口。多重继承接口不会带来二义性和复杂性问题。接口类只是一个功能声明,并不是功能实现,子类需要根据功能说明定义功能实现。多继承带来了一些争议,但是接口继承可以说一种毫无争议的运用了。接口类中只有函数原型定义,没有任何数据定义。注意:除了析构函数外,其他声明都是纯虚函数。原创 2024-07-22 00:06:25 · 180 阅读 · 0 评论 -
C++-类-多态4:抽象基类和纯虚函数(pure virtual function)
在设计时,常常希望基类仅仅作为其派生类的一个接口。这就是说,仅想对基类进行向上类型转换,使用它的接口,而不希望用户实际的创建一个基类的对象。同时创建一个纯虚函数允许接口中放置成员原函数,而不一定要提供一段可能对这个函数毫无意义的代码。做到这点,可以在基类中加入至少一个纯虚函数(pure virtual function),使得基类称为抽象类(abstract class).是为了将子类公共的操作抽象出来,可以通过一个公共接口来操纵一组类,且这个公共接口不需要事先(或者不需要完全实现)。可以创建一个公共类.原创 2024-07-22 00:06:18 · 886 阅读 · 0 评论 -
C++-类-多态3:C++如何实现动态绑定
在对象构建的时候,也就是在对象初始化调用构造函数的时候。当编译器发现我们的类中有虚函数的时候,编译器会创建一张虚函数表,把虚函数的函数入口地址放到虚函数表中,并且在类中秘密增加一个指针,这个指针就是vpointer(缩写vptr),这个指针是指向对象的虚函数表。在多态调用的时候,根据vptr指针,找到虚函数表来实现动态绑定。当程序执行到这里,会去animal指向的空间中寻找vptr指针,通过vptr指针找到func1函数,由于子类重写基类的func1函数,所以调用func1时,调用的是子类的func1.原创 2024-07-22 00:06:07 · 285 阅读 · 0 评论 -
C++-类-多态2:向上类型转换及问题【父类引用或指针可以指向子类对象,通过父类指针或引用来操作子类对象】
对于一种编译语言,编译器并不知道实际的对象类型(编译器并不知道Animal类型的指针或引用指向的实际的对象类型)。这个时候由于DoBussiness的参数类型是Animal&,编译器确定了应该调用的speak是Animal::speak的,而不是真正传入的对象Dog::speak。C++动态多态性是通过虚函数来实现的,虚函数允许子类(派生类)重新定义父类(基类)成员函数,而子类(派生类)重新定义父类(基类)虚函数的做法称为覆盖(override),或者称为重写。是根据指向对象的指针或引用的类型。原创 2024-07-22 00:05:57 · 649 阅读 · 0 评论 -
C++-类-多态1:多态基本概念
多态性改善了代码的可读性和组织性,同时也使创建的程序具有可扩展性,项目不仅在最初创建时期可以扩展,而且当项目在需要有新的功能时也能扩展。c++支持编译时多态(静态多态)和运行时多态(动态多态),运算符重载和函数重载就是编译时多态,而派生类和虚函数实现运行时多态。如果函数的调用,在编译阶段就可以确定函数的调用地址,并产生代码,就是静态多态(编译时多态),就是说地址是早绑定的。而如果函数的调用地址不能编译不能在编译期间确定,而需要在运行时才能决定,这这就属于晚绑定(动态多态,运行时多态)。原创 2024-07-22 00:05:47 · 397 阅读 · 0 评论 -
C++-类-继承和派生7:多继承【虚基类】【虚继承解决了菱形继承所带来的二义性问题】
当使用虚继承时,虚基类是被共享的,也就是在继承体系中无论被继承多少次,对象内存模型中均只会出现一个虚基类的子对象(这和多继承是完全不同的)。工程开发中真正意义上的多继承是几乎不被使用,因为多重继承带来的代码复杂性远多于其带来的便利,多重继承对代码维护性上的影响是灾难性的,在设计方法上,任何多继承都可以用单继承代替。多继承会带来一些二义性的问题, 如果两个基类中有同名的函数或者变量,那么通过派生类对象去访问这个函数或变量时就不能明确到底调用从基类1继承的版本还是从基类2继承的版本?原创 2024-07-22 00:05:02 · 873 阅读 · 0 评论 -
C++-类-继承和派生6:继承中的静态成员特性
改变基类函数的某个特征,返回值或者参数个数,将会隐藏基类重载的函数。静态成员函数不能是虚函数(virtual function).重定义一个函数,基类中重载的函数被隐藏。基类静态成员属性将被隐藏。原创 2024-07-22 00:04:48 · 356 阅读 · 0 评论 -
C++-类-继承和派生5:非自动继承的函数
另外operator=也不能被继承,因为它完成类似构造函数的行为。也就是说尽管我们知道如何由=右边的对象如何初始化=左边的对象的所有成员,但是这个并不意味着对其派生类依然有效。构造函数和析构函数用来处理对象的创建和析构操作,构造和析构函数只知道对它们的特定层次的对象做什么,也就是说构造函数和析构函数不能被继承,必须为每一个特定的派生类分别创建。在继承的过程中,如果没有创建这些函数,编译器会自动生成它们。不是所有的函数都能自动从基类继承到派生类中。原创 2024-07-22 00:04:38 · 137 阅读 · 0 评论 -
C++-类-继承和派生4:继承中同名成员的处理方法
通过改变函数返回类型的方式重新定义了基类的func1函数,则从基类继承来的没有重新定义的重载版本的函数将被隐藏。通过改变函数参数列表的方式重新定义了基类的func1函数,则从基类中继承来的其他重载版本被隐藏,不可访问。重定义了Base类的myfunc函数,derive1可访问func1及其重载版本的函数。任何时候重新定义基类中的一个重载函数,在新类中所有的其他版本将被自动隐藏.派生类和基类成员属性重名,子类访问成员默认是子类成员。重载func1之后,基类的函数被隐藏。没有重新定义的重载版本被隐藏。原创 2024-07-22 00:04:30 · 905 阅读 · 0 评论 -
C++-类-继承和派生3:继承中的构造和析构
在C++编译器的内部可以理解为结构体,子类是由父类成员叠加子类新成员而成:classAclasspublicintmA;intmB;classBclasspublicAclasspublicintmC;classCclasspublicBclasspublicintmD;voidtest(){cout原创 2024-07-22 00:04:21 · 539 阅读 · 0 评论 -
C++-类-继承和派生2:派生类访问控制
不可访问基类protected属性。不可访问基类protected属性。不可访问基类protected属性。不可访问基类protected属性。可访问基类protected属性。可访问基类protected属性。可访问基类protected属性。不可访问基类private属性。不可访问基类private属性。不可访问基类private属性。不可访问基类private属性。不可访问基类private属性。不可访问基类private属性。不可访问基类private属性。不可访问基类private属性。原创 2024-07-22 00:04:12 · 488 阅读 · 0 评论 -
C++-类-继承和派生1:继承概述
派生类定义格式:Class派生类名继承方式基类名//派生类新增的数据成员和成员函数三种继承方式:public: 公有继承private: 私有继承protected: 保护继承从继承源上分:单继承:指每个派生类只直接继承了一个基类的特征多继承:指多个基类派生出一个派生类的继承关系,多继承的派生类直接继承了不止一个基类的特征。原创 2024-07-22 00:04:01 · 947 阅读 · 0 评论 -
C++-类-运算符重载1:运算符重载基本概念
这种定义很像一个普通的函数定义,只是函数的名字由关键字operator及其紧跟的运算符组成。运算符被定义为全局函数(对于一元是一个参数,对于二元是两个参数)还是成员函数(对于一元没有参数,对于二元是一个参数-此时该类的对象用作左耳参数)定义重载的运算符就像定义函数,只是该函数的名字是operator@,这里的@代表了被重载的运算符。对于运算符重载,另外一个常见的反应是恐慌:突然之间,C运算符的含义变得不同寻常了,一切都变了,所有C代码的功能都要改变!对于内置的数据类型的表示总的所有运算符是不可能改变的。原创 2024-07-22 00:03:49 · 412 阅读 · 0 评论 -
C++-类-运算符重载9:不要重载&&、||
说得更具体一些,内置版本版本特殊之处在于:内置版本的&&和||首先计算左边的表达式,如果这完全能够决定结果,就无需计算右边的表达式了--而且能够保证不需要。这边却是,先运算(complex1+complex2),导致,complex1的flag变为complex1+complex2的值, complex1.a = 1。根据内置&&的执行顺序,我们发现这个案例中执行顺序并不是从左向右,而是先右猴左,这就是不满足我们习惯的特性了。原来情况,应该从左往右运算,左边为假,则退出运算,结果为假。原创 2024-07-22 00:03:40 · 257 阅读 · 0 评论 -
C++-类-运算符重载8:函数调用符号()重载
classComplexpublicintAddintxinty){returnxy;intoperator()(intxinty){returnxy;voidtest01(){;cout原创 2024-07-22 00:03:11 · 142 阅读 · 0 评论 -
C++-类-运算符重载7:等于和不等于(==、!=)运算符重载
classComplexpublicComplexcharnameintidintage){this->pNamenewcharstrlenname1strcpythis->pNamenamethis->mIDid;this->mAgeage;//重载==号操作符booloperator==(constComplexcomplex){ifstrcmpthis->pName。原创 2024-07-21 01:12:50 · 269 阅读 · 0 评论 -
C++-类-运算符重载6:赋值(=)运算符重载
赋值符常常初学者的混淆。这是毫无疑问的,因为’=’在编程中是最基本的运算符,可以进行赋值操作,也能引起拷贝构造函数的调用。如果没有重载赋值运算符,编译器会自动创建默认的赋值运算符重载函数。对于本例来讲,无论如何执行这些赋值运算都是无害的,但如果对类的实现进行修改,那么将会出现差异;由于person2已经创建,不需要再调用构造函数,这时候调用的是重载的赋值运算符。常见错误,当准备给两个相同对象赋值时,应该首先检查一下这个对象是否对自身赋值了。如果一个对象还没有被创建,则必须初始化,也就是调用构造函数。原创 2024-07-21 01:12:40 · 350 阅读 · 0 评论 -
C++-类-运算符重载5:指针运算符(*、->)重载
如果忘记释放,那么就会造成内存泄漏。重载指针的->、*操作符。原创 2024-07-21 01:12:32 · 235 阅读 · 0 评论 -
C++-类-运算符重载4:自增自减(++/--)运算符重载
解决办法很简单,例如当编译器看到++a(前置++),它就调用operator++(a),当编译器看到a++(后置++),它就会去调用operator++(a,int).调用代码时候,要优先使用前缀形式,除非确实需要后缀形式返回的原值,前缀和后缀形式语义上是等价的,输入工作量也相当,只是效率经常会略高一些,由于前缀形式少创建了一个临时对象。对于++和--而言,后置形式是先返回,然后对象++或者--,返回的是对象的原值。前置形式,对象先++或--,返回当前对象,返回的是新对象。原创 2024-07-21 01:12:23 · 490 阅读 · 0 评论 -
C++-类-运算符重载3:可重载的运算符
这样的限制有意义,否则,所有这些行为产生的运算符只会混淆而不是澄清寓语意。几乎C中所有的运算符都可以重载,但运算符重载的使用时相当受限制的。不能使用C中当前没有意义的运算符。不能改变运算符的参数个数。不能改变运算符优先级。原创 2024-07-21 01:12:13 · 229 阅读 · 0 评论 -
C++-类-运算符重载2:运算符重载碰上友元函数
友元函数是一个全局函数,和我们上例写的全局函数类似,只是友元函数可以访问某个类私有数据。原创 2024-07-21 01:12:05 · 207 阅读 · 0 评论 -
C++-类:友元(在类的外部访问类的私有成员)【①全局函数做友元函数;②类做友元类;③类成员函数做友元函数】
类的主要特点之一是数据隐藏,即类的私有成员无法在类的外部(作用域之外)访问。但是,有时候需要在类的外部访问类的私有成员,怎么办?解决方法是使用友元函数,友元函数是一种特权函数,c++允许这个特权函数访问私有成员。这一点从现实生活中也可以很好的理解:比如你的家,有客厅,有你的卧室,那么你的客厅是Public的,所有来的客人都可以进去,但是你的卧室是私有的,也就是说只有你能进去,但是呢,你也可以允许你的闺蜜好基友进去。程序员可以把一个全局函数、某个类中的成员函数、甚至整个类声明为友元。原创 2024-07-21 01:11:57 · 704 阅读 · 0 评论 -
C++-类:this指针【this指针永远指向当前对象】
c++规定,this指针是隐含在对象成员函数内的一种指针。当一个对象被创建后,它的每一个成员函数都含有一个系统自动生成的隐含指针this,用以保存这个对象的地址,也就是说虽然我们没有写上this指针,编译器在编译的时候也是会加上的。因此this也称为“指向本对象的指针”,this指针并不是对象的一部分,不会影响sizeof(对象)的结果。this指针是C++实现封装的一种机制,它将对象和该对象调用的成员函数连接在一起,在外部看来,每一个对象都拥有自己的函数成员。This指针指向被调用的成员函数所属的对象。原创 2024-07-21 01:11:45 · 621 阅读 · 0 评论 -
C++-类:成员变量和函数的存储【只有非静态成员变量才属于特定对象】【非静态成员函数、静态成员变量、静态成员函数不属于特定对象】
在c语言中,“分开来声明的,也就是说,语言本身并没有支持“数据”和“函数”之间的关联性我们把这种程序方法称为“程序性的”,由一组“分布在各个以功能为导航的函数中”的算法驱动,它们处理的是共同的外部数据。c++实现了“封装”,那么数据(成员属性)和操作(成员函数)是什么样的呢?通过上面的案例,我们可以的得出:C++类对象中的变量和函数是分开存储。“数据”和“处理数据的操作(函数)”是分开存储的。静态数据成员并不保存在类对象中。非静态成员函数不保存在类对象中。静态成员函数也不保存在类对象中。原创 2024-07-21 01:11:36 · 878 阅读 · 0 评论 -
C++-类-静态成员2:静态成员实现单例模式【为了让类中只有一个实例,实例不需要自己释放】【将默认构造和拷贝构造私有化,内部维护一个对象指针,私有化唯一指针,对外提供getInstance方法来访问】
在单例类的内部实现只生成一个实例,同时它提供一个静态的getInstance()工厂方法,让客户可以访问它的唯一实例;在单例类内部定义了一个Singleton类型的静态对象,作为外部共享的唯一实例。单例模式是一种常用的软件设计模式。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。用单例模式,模拟公司员工使用打印机场景,打印机可以打印员工要输出的内容,并且可以累积打印机使用次数。原创 2024-07-21 01:11:26 · 276 阅读 · 0 评论 -
C++-类-静态成员1:静态成员变量、静态成员函数、const静态成员属性
在类定义中,它的成员(包括成员变量和成员函数),这些成员可以用关键字static声明为静态的,称为静态成员。不管这个类创建了多少个对象,静态成员只有一个拷贝,这个拷贝被所有属于这个类的对象共享。原创 2024-07-21 01:11:17 · 859 阅读 · 0 评论 -
C++-类-动态对象创建1:new【摒弃C中的malloc和free函数】【创建:Person* person = new Person(“tom“)】【销毁:delete person】
换句话说,person指针指向的是一个单一的对象还是一个数组对象,由于单一对象和数组对象的内存布局是不同的。当我们创建数组的时候,总是需要提前预定数组的长度,然后编译器分配预定长度的数组空间,在使用数组的时,会有这样的问题,数组也许空间太大了,浪费空间,也许空间不足,所以对于数组来讲,如果能根据需要来分配空间大小再好不过。使用了new也搭配使用了delete,问题在于Person有10个对象,那么其他9个对象可能没有调用析构函数,也就是说其他9个对象可能删除不完全,因为它们的析构函数没有被调用。原创 2024-07-21 01:11:06 · 598 阅读 · 0 评论 -
C++-类-动态对象创建3:delete void*可能会出错【当用void* 接受new出来的指针时,会出现释放的问题】
如果对一个void*指针执行delete操作,这将可能成为一个程序错误,除非指针指向的内容是非常简单的,因为它将不执行析构函数.以下代码未调用析构函数,导致可用内存减少。、free和new、delete可以混搭使用吗?也就是说malloc分配的内存,可以调用delete吗?通过new创建的对象,可以调用free来释放吗?原创 2024-07-21 01:10:57 · 275 阅读 · 0 评论 -
C++-类-动态对象创建2:使用new和delete创建数组【Person * pArray = new Person[10];】【delete [] pArray;】
当创建一个对象数组的时候,必须对数组中的每一个对象调用构造函数。,除了在栈上可以聚合初始化,必须提供一个默认的构造函数。使用new和delete在堆上创建数组非常容易。创建堆上对象数组必须提供构造函数。创建整型数组并初始化。原创 2024-07-21 01:10:48 · 924 阅读 · 0 评论 -
C++-类:初始化列表【Person(int a, int b, int c):mA(a),mB(b),mC(c){}】【构造函数后面+:属性(参数),属性(参数,...)】【不一定全部初始化】
构造函数和其他函数不同,除了有名字,参数列表,函数体之外还有初始化列表。初始化成员列表(参数列表)只能在构造函数使用。初始化列表方式初始化。原创 2024-07-21 01:10:38 · 186 阅读 · 0 评论 -
C++-类:深拷贝和浅拷贝
一般情况下,浅拷贝没有任何副作用,但是当类中有指针,并且指针指向动态分配的内存空间,析构函数做了动态内存释放的处理,会导致内存问题。当类中有指针,并且此指针有动态分配空间,析构函数做了释放处理,往往需要自定义拷贝构造函数,自行给指针动态分配空间,深拷贝。同一类型的对象之间可以赋值,使得两个对象的成员变量的值相同,两个对象仍然是独立的两个对象,这种情况被称为。用对象p1初始化对象p2,调用c++提供的默认拷贝构造函数。原创 2024-07-21 01:10:29 · 399 阅读 · 0 评论 -
C++-类:构造函数调用规则【默认下,c++编译器为我们写的类增加3个函数:①默认构造函数(无参,函数体为空);②默认析构函数(无参,函数体为空);③默认拷贝构造函数,对类中非静态成员属性简单值拷贝】
4.3.3 构造函数调用规则默认情况下,c++编译器至少为我们写的类增加3个函数默认构造函数(无参,函数体为空)默认析构函数(无参,函数体为空)默认拷贝构造函数,对类中非静态成员属性简单值拷贝如果用户定义拷贝构造函数,c++不会再提供任何默认构造函数如果用户定义了普通构造(非拷贝),c++不在提供默认无参构造,但是会提供默认拷贝构造原创 2024-07-21 01:10:20 · 222 阅读 · 0 评论 -
C++-类:构造函数的分类及调用【①按参数类型分为:无参构造函数、有参构造函数】【②按类型分为:普通构造函数、拷贝构造函数(复制构造函数)】
我们从常理来分析的话,这个匿名对象和这个局部的p对象是相同的两个对象,那么如果能直接返回p对象,就会省去一个拷贝构造和一个析构函数的开销,在程序中一个对象的拷贝也是非常耗时的,如果减少这种拷贝和析构的次数,那么从另一个角度来说,也是编译器对程序执行效率上进行了优化。当A(b) 有变量来接的时候,那么编译器认为他是一个匿名对象,当没有变量来接的时候,编译器认为你A(b) 等价于 A b.为A的实例化对象,A a = A(b) 和 A(b)的区别?拷贝构造函数(复制构造函数) 使用另一个对象初始化本对象。原创 2024-07-21 01:10:09 · 544 阅读 · 0 评论 -
C++-对象:构造函数、析构函数(用于对象的初始化和清理)
那么随着我们使用手机和电脑的时间越来越久,那么电脑和手机会慢慢被我们手动创建很多文件数据,某一天我们不用手机或电脑了,那么我们应该将电脑或手机中我们增加的数据删除掉,保护自己的信息数据。对象的初始化和清理也是两个非常重要的安全问题,一个对象或者变量没有初始时,对其使用后果是未知,同样的使用完一个变量,没有及时清理,也会造成一定的安全问题。那么我们c++中OO思想也是来源于现实,是对现实事物的抽象模拟,具体来说,当我们创建对象的时候,这个对象应该有一个初始状态,当对象销毁之前应该销毁自己创建的一些数据。原创 2024-07-21 01:09:58 · 420 阅读 · 0 评论 -
C++-类:类的封装【①把变量(属性)和函数(操作)合成一个整体,封装在一个类中,②对变量和函数进行访问控制:将成员变量设置为private,通过成员函数(设置为public)来访问和修改成员变量】
定义一个结构体用来表示一个对象所包含的属性,函数用来表示一个对象所具有的行为,这样我们就表示出来一个事物,在c语言中,行为和属性是分开的,也就是说吃饭这个属性不属于某类对象,而属于所有的共同的数据,所以不单单是PeopleEat可以调用Person数据,AnimalEat也可以调用Person数据,那么万一调用错误,将会导致问题发生。现实世界的事物所具有的共性就是每个事物都具有自身的属性,一些自身具有的行为,所以如果我们能把事物的属性和行为表示出来,那么就可以抽象出来这个事物。对只读属性进行只读访问。原创 2024-07-21 01:09:47 · 846 阅读 · 0 评论