首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

C++之类和对象

(在C语言中是习惯先定义变量再使用),但是一般我们见到的C++程序都是将成员函数写在成员变量的前面,这是为什么呢?...其实这也是可以预料到的,毕竟如果空类是零字节的话,实例化出来的对象就无法分辨。其实主要原因是,C++有默认的成员函数,就算我们写编译器也会自动生成,这个后面会提到。...可以看到,我们写编译器确实会有一个构造函数来初始化,不过这个初始化出来的数太随机值了,看起来就像乱码一样。这是为什么?...,对自定义类型调用其自身的赋值重载函数我们可以理解为:需要写析构函数的类就需要写赋值重载函数,不需要写析构函数的类就不要写赋值重载函数。...因为我们在类中定义的这个函数,所以第一个参数默认为隐藏的this指针,也就是左参数必须是类对象,因此这个运算符应该要这样使用: 可以看到这样使用就没有任何问题了,但是这样的可读性不高,重载这个运算符又显得没有意义

1.1K00

C++打怪升级(五)- 类和对象入门2

C++的类中,便将一些类经常会用到的功能由编译器默认以函数的方式隐士的实现这样就简化了类的实现,一些功能我们可以不需要显式的写出来了,编译器帮我们完成了。...先说结论: 要看我们对类的具体需求,编译器默认生成的构造函数能够满足我们的需求就不要写,不满足时才需要手动写; 首先,并不是说有内置类型的变量就一定要写,自定义类型就一定不需要写; 内置类型...自定义类型 不需要写: 队列类用两个栈模拟实现时就不需要我们写构造函数,队列会调用栈自己的构造函数。...需要写: 队列类用两个栈模拟实现,但是我们对两个栈的大小给出了明确的大小,这样栈的构造函数初始化的大小就不符合我们期望的初始大小了,这种情况我们就需要手动写队列类的构造函数了。...与构造函数、析构函数、拷贝构造、赋值运算符重载不同,取地址重载我们基本不需要实现,除非有特殊需求,我们也不会在此花费多少时间

72320
您找到你想要的搜索结果了吗?
是的
没有找到

C++】类的六大默认成员函数及其特性(万字详解)

: 但是如果当我们显式自定义构造函数,系统就不会再生成那个无参的构造函数了,这时我们再在主函数调用无参的构造函数就会失败: class Date { public: //用户自定义的显式带参构造函数...,再去调用默认构造函数系统就不会生成了: 注意,在上述举例中,我们自定义的带参构造函数仅是为了证实 : 如果用户自定义构造函数,系统就不会再生成默认构造函数(这个系统生成的构造函数规定是无参的),如果用户自定义的是无参的构造函数...,那么系统同样不会生成构造函数,但是这时在主函数调用无参的构造函数是可以正常运行的,这是因为这时编译器调用的就是用户自定义的无参构造函数,但这样无法明显印证"用户自定义构造函数,系统就不会再生成无参的默认构造函数...这涉及一项C++的规定,即:按值传递会导致被调用函数使用调用程序中的值的拷贝 即,当我们函数传值调用时,实际上是将原变量拷贝一份给形参使用: 而对于C++中的自定义类型...,虽然仅仅只减少了一次拷贝构造及析构,但如果我们拷贝构造的对象是一个有几万个数据的动态栈或者其他结构时,小小一次拷贝构造节省的时间就非常可观: 但还有一点需要注意,不能够将函数内部创建的变量通过引用返回值返回给主函数

10710

C++】类和对象(第二篇)

比如上面我们定义的那个Date类,如果要写它的构造函数就应该是这样的: 对象实例化时编译器自动调用对应的构造函数构造函数我们初始化对象就不用再手动初始化了,实例化一个对象时编译器会自动调用其对应的构造函数...这是不是就达到我们想要的效果。 但是要注意,调用无参构造函数的时候我们要写这样Date d1();即后面不要加括号。...为什么说只能有一个呢,因为我们调用这些构造函数是不是都不用传参啊,那这样如果同时存在多个的话,编译器就不知道到底该调哪个。 这个问题我们上面也有提到过的。 3....一运行发现我们的程序挂掉了。 为什么这样呢,刚才Date类也都是内置类型,为啥就没事呢?...所以为什么程序崩溃,就是我们这里对野指针进行free

9610

C++初阶】类和对象修炼中

一.构造函数 首先给大家聊聊为什么C++中要设计出构造函数,构造函数完成的是对象的初始化Init(),因为在实际代码编写过程中,我们往往会忘记写对象的初始化函数Init(),甚至还会出现写了忘记调用的情形...所以C++中就出现构造函数,如果你没写的话,编译器就帮我们写好初始化函数,并且在对象创建的时候自动调用。...默认构造函数并不仅仅指的是我们写,编译器默认生成的; 编译器默认生成的只是三种构造函数重载的默认构造函数的一种,也就是下图中我们显式写出来的无参构造函数....: 这里我给大家演示的是将函数定义成了全局的,这样第一个参数就不是this指针,但是C++编译器同样支持把调用函数的方式处理成我们从小到大都熟悉的形式:d1==d2,而非 operator==(d1,d2...,而非全局的函数(也没法定义成全局的,因为成员变量几乎都是私有访问的) 有运算符重载得铺垫,我们就可以给大家讲什么是赋值运算符重载.

50650

C++修炼之路】3. 类和对象(中)

默认成员函数:又称特殊成员函数,用户没有显式实现,编译器会生成的成员函数称为默认成员函数。即:我们写,编译器就会自己生成一个;我们自己写了,编译器就不会生成。...同时也对应上面的条款:默认构造函数只能有一个 2.3 构造函数实现栈Stack的初始化 对于栈来说,初始化是必要的,但是我们在创建栈的时候有可能忘记调用其初始化,因此在C++中,我们可以通过构造函数对其自动的初始化...虽然说是可以的,但在这里我还是想记录一下我当时思考的过程:在了解拷贝会发生死递归之后,但是又看见指针传就不会死递归,我就产生了一个这样的疑惑:传参是拷贝值产生死递归,用指针也是传地址,这个地址也算是参数吗...然后拷贝这个地址,这样也会发生死递归吗,为什么还可以呢?...我们知道对于默认的6个成员函数都有一个共性,即当我们这样函数时系统会默认生成一个这样函数,前面的构造、拷贝、拷贝构造都已经展示过,下面将我们的赋值运算符重载函数去掉,让系统自动生成一个赋值运算符重载函数再运行会是什么样的结果

48800

C++】类和对象 (中篇)

,不要在对象后面带括号,这样使得编译器分不清这是在实例化对象还是函数声明; ---- 2、特性分析 – 自动生成 在构造函数的第5点特性中我们提到:如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数...,直接使用编译器自动生成的构造函数即可;(虽然自动生成的构造函数对内置类型处理,但本来Date类就不需要我们做任何处理) Stack: class Stack { public: Stack(int...,可以理解为需要写析构函数就需要写拷贝构造,不需要写析构函数就不要写拷贝构造; 拷贝构造的经典使用场景: 使用已存在对象创建新对象; 函数参数类型为类类型对象; 函数返回值类型为类类型对象; --...,但对于有资源申请,需要进行深拷贝的对象来说就会发生不可控的事情,具体案例我们在第四点特性中讲解; 在 《Effective C++》中对赋值重载函数自我赋值的解释是这样的: if(this == &...,对自定义类型调用其自身的赋值重载函数我们可以理解为:需要写析构函数的类就需要写赋值重载函数,不需要写析构函数的类就不要写赋值重载函数; ---- 七、取地址及 const 取地址重载 1、const

64500

C++初阶 入门(2)

c++中,定义函数的时候可以让最右边的连续若干个参数有缺省值,在调用函数的时候,如果写相应位置的参数,则调用的参数就为缺省值,如此便构成了缺省函数 1.2为什么要有缺省函数 有的小伙伴可能会觉得...但其实在实际编写代码的过程中,我们有些时候会频繁地调用某个函数,而这个函数的其他参数是固定值,在c中遇到这种情况,便只能老实写参数,即使这几个参数的数值你已经写了无数次,但你依然得去写它,而在c++中...,你使用缺省函数就可以避免这一情况,你完全可以将一些不会变的参数或不常变的参数进行缺省,这样子不仅可以节约大量的时间,还可以大大提升代码的可读性。...而返回值是不作为函数重载的考虑范围的,也就是说,两个函数即使参数类型和个数都相同,它们的返回值不同也是构成函数重载的。...引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何 一个同类型实体 4. 没有NULL引用,但有NULL指针 5.

12410

类和对象之六大基础函数

(你写了编辑器就不会生成,你写编辑器就会自动生成,是否写构造函数,要考虑编辑器自动生成的构造函数是否可满足需求,在上述日期类中,自动生成的构造函数可不满足我们的需求,原因看下文,所以我们要自己写) class...对,没错,不管了0.0,即随机值(我猜测是编辑器认为它是内置的,大家都门清,就不管你),这也是为啥上文的日期类对象要写构造函数的原因,一个日期怎么能随机呢?)...如果类中没有申请资源时,析构函数可以写,直接使用编译器生成的默认析构函数,比如 Date类;有资源申请时,一定要写,否则会造成资源泄漏,比如Stack类  5.赋值运算符重载(自定义运算符)...5.1 运算符重载 C++在扩展类的功能后,又来一个新问题,在我们完成类的定义后,我们定义的类作为单独的一个类对象除了能用于各种需求的数据存储,但是不同对象之间却没有太多的交流。...,使用编译器生成的默认取地址的重载即可,只有特殊情况,才重载,比如想让别人获取到指定的内容(不过这样就无法取的类对象的地址);

47820

类与对象中篇

6.如果类中没有申请资源时,析构函数可以写,直接使用编译器生成的默认析构函数,比如:Date类,有资源申请时,一定要写否则会造成资源泄漏,比如Stack类。...5.赋值运算符重载 运算符重载C++为了使自定义类型也能使用运算符同时增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型和参数列表与普通的函数类似...operator==(d1,d2);函数放在类中d1.operator==(d2) //也可以显示调用 但一般这样 //operator==(d1, d2);//d1.operator==(d2)...,就和编译器在类中生成的默认赋值运算符重载冲突,故赋值运算符重载只能是类的成员函数。...// C++规定:后置++重载时多增加一个int类型的参数,但调用函数时该参数不用传递,编译器自动传递 // 注意:后置++是先使用后+1,因此需要返回+1之前的旧值,故在实现时需要先将this保存一份

50230

C++】类和对象(中)(万字详解)

对,我们多多少少会忘记,所以在C++类和对象中呢,就出现这样函数:构造函数和析构函数 ---- 一、类的六个默认成员函数 默认成员函数:用户没有显式实现,编译器会生成的成员函数称为默认成员函数。...(重载(点击链接有详细解释),函数名相同,参数不同就构成重载为什么要构成重载呢?...他们都是默认成员函数,自己写,编译器就会默认生成。关键在于,编译器默认提供的,能不能符合我们的需求! 那么我们之前总结过,拷贝构造,当要调用析构函数时,就需要我们自己去写,赋值重载也是一样的。...); ---- 那么有时候我们也会遇到这样的情况:cout<<d1<<d2; 链式访问,这就和之前的赋值重载很一样,需要返回值,不同的是,<<的链式访问是从左到右的。...2.取地址重载 六大类默认成员函数就是:自己写,编译器会给出。 当然,取地址重载例外,所以在大多数的时候,我们使用取地址都不需要自己写,除非一种情况!!

41030

C++修行之道】类和对象(五)日期类的实现、const成员、取地址及const和取地址操作符重载

C++中,对象的复制可能是一个昂贵的操作。 链式操作:通过返回引用,可以支持链式操作。...例如,可以这样写代码:--date = anotherDate; 注意:this指向的对象函数结束后不会销毁,故以引用方式返回提高效率 后置运算符的语义是“先返回,再操作”。...前置++和后置++都是一元运算符,为了让前置++与后置++形成能正确重载 C++规定:后置++重载时多增加一个int类型的参数,但调用函数时该参数不用传递,编译器自动传递。...class A { public: // 我们不实现,编译器会自己实现,我们实现编译器就不会自己实现 // 一般不需要我们自己实现 // 除非不想让别人取到这个类型对象的真实地址 A* operator...,使用编译器生成的默认取地址的重载即可,只有特殊情况,才重载,比如想让别人获取到指定的内容!

7810

C++C++入门基础

我们可以直接将命名空间在全局展开,这样就不用每次都加个作用域限定符去访问了!!...8.1 函数重载的概念 在c语言中,不支持函数同名,即每个函数名都只能被定义一次,这就在某些情况会造成困扰,比如Add函数我们设置的时候想让他计算int类型,但是如果我们想再设置一个这样函数计算...double类型,就不能直接用Add这个名字,而是还得写成Addd,如果想计算float,得写成Addf,这其实是不利于理解的,我们的祖师爷本贾尼博士为了解决这种情况,让c++支持函数重载的功能。...+支持函数重载的原理--名字修饰(name Mangling) 为什么c++支持函数重载,而c不支持呢?...通过这里就理解了C语言没办法支持重载,因为同名函数没办法区分。而C++是通过函数修 饰规则来区分,只要参数不同,修饰出来的名字就不一样,就支持重载

16210

C++类和对象(中)

所以,我们可以: 面向需求:编译器默认生成就可以满足,就不用自己写,不满足就需要自己写 Date Stack的构造函数需要自己写 MyQueue构造函数就不需要自己写,默认生成就可以用。...无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。注意:无参构造函数、全缺省构造函数我们没写编译器默认生成的构造函数,都可以认为是默认构造函数 为什么只能有一个?...这里有个小细节:如果我们写的构造函数,不成为默认构造函数,那么如果我们在定义对象,没有去调用我们非构造函数的时候,就会出现编译器报出这样的错误:不存在默认构造函数为什么?...编译器生成的默认拷贝构造函数已经可以完成字节序的值拷贝,还需要自己显式实现吗?当然像日期类这样的类是没必要的。那么下面的类呢?验证一下试试。...为什么报错?是因为在调用析构函数的时候报错了! 为什么? 所以:类中如果没有涉及资源申请时,拷贝构造函数是否写都可以;一旦涉及到资源申请时,则拷贝构造函数是一定要写的,否则就是浅拷贝。

1.2K20

C++C++入门—初识构造函数 , 析构函数,拷贝构造函数,赋值运算符重载

默认成员函数:用户没有显式实现,编译器会生成的成员函数称为默认成员函数 我们实现,编译器就不会生成了 1 构造函数 构造函数是一个特殊的成员函数,名字与类名相同,创建类类型对象时由编译器自动调用...注意:析构函数不能重载 对象生命周期结束时,C++编译系统系统自动调用析构函数。...如果类中没有申请资源时,析构函数可以写,直接使用编译器生成的默认析构函数,比如Date类;有资源申请时,一定要写,否则会造成资源泄漏,比如Stack类 3 拷贝构造函数 拷贝构造函数:只有单个形参,该形参是对本类类型对象的引用...拷贝构造函数典型调用场景: 使用已存在对象创建新对象 函数参数类型为类类型对象 函数返回值类型为类类型对象 4 赋值运算符重载 运算符重载 C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数...,例如:内置的整型+, 能改变其含义作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐藏的this .* :: sizeof ?

14110

C++初阶类与对象(三):详解复制构造函数和运算符重载

上次介绍构造函数和析构函数C++初阶类与对象(二):详解构造函数和析构函数 今天就来接着介绍新的内容: 文章目录 1.拷贝构造函数 1.1引入和概念 1.2特性 2.赋值运算符重载 2.1运算符重载...拷贝构造函数的参数只有一个且必须是类类型对象的引用(&),使用传值方式编译器直接报错,因为会引发无穷递归调用 为什么会无限递归:当我们传值调用函数时,首先传参–>因为是传值会调用新的一个拷贝构造–>...不会这样干 使用友元函数 友元函数后面会给大家详解,在这里先下结论:能不使用友元函数就不使用 放在类里面 我们选择直接重载成成员函数 2.3运算符重载示例 我们就先使用大家最为熟悉的日期类作为演示...和上面拷贝构造一样:日期类这样的是不需要实现的(使用默认的就够了);但是像是Stack类这样的一旦涉及到资源申请时,则拷贝构造函数是一定要写的(要用深拷贝) 赋值运算符重载与拷贝构造调用区别: int...==,这样调用时就是d1<<cout

14210

C++入门】—— C++入门 (中)_引用

函数重载 函数重载通俗一点来讲就是C++上的一词多义!...return x; } // 这种情况构成函数重载!!!...2.2 函数重载原理 C语言为什么不支持函数重载 我们在之前环境与预处理讲过,代码变成可执行程序需要经过四个阶段 预处理 编译 汇编 链接 Test.cpp 预处理!...,因此C语言不支持函数重载C++的汇编中,我们发现这两个函数 C++函数参数的类型,数量,顺序不同在符号表中的名字就不一样,就可以区分两个函数,所以支持重载 C语言符号表中只有一个函数名...总结 本小结我们了解C++入门的三大知识,缺省参数,函数重载,以及引用,在后面C++的学习中这些都极为重要,尤其是引用。到这里我们已经入门一大半,还有最后一点入门知识,我们期待下回分解!

8110

C++C++基础语法

---- 4.std官方库定义的命名空间 一个命名空间就定义一个新的作用域,命名空间中的所有内容都局限于该命名空间中 C++中,我们使用的函数都在std命名空间里,所以在我们使用时,经常会这样:...命名冲突,但是我们也可以把频率较高使用的单独放开围墙,这样我们就不需要重复去写 cout是c++中的输出,相当于c的printf,所以将其单独放开的话,就是这样的:using std::cout; 你懂了吗...当参数类型不同的时候,我们需要再去写一个函数,而且还不能同名,如果重名,编译器不会通过,但如果在C++中,就可以使用,这叫做 函数重载。...---- 八、内联函数我们编译代码的时候,总会有一些短小的代码,但需要我们反复去调用,那么调用函数就会建立栈帧,但是宏可以解决这样的问题,预先定义好宏,在预处理时,都会被替换直接展开,不需要写函数。...inline建议声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址 ,链接就会找不到。 只要加了inline内联,就不会生成符号表。

1.3K20

剖析深拷贝与浅拷贝,探究重载返回引用还是对象

(2) c++中有些重载运算符为什么要返回引用? 为了理解第(2)点,我们需要知道什么是深拷贝,什么是浅拷贝,分配内存是在堆上,还是在栈上!...也就是说,即使我们overload这两种operation,仍然可以运行。那么,我们到底不需要overload这两种operation 呢?...我们也可以这样重载赋值运算符 void operator=(A &a);即返回任何值。如果这样的话,他将不支持客户链式赋值 ,例如a=b=c will be prohibited!...同时,赋值函数首先要释放掉对象自身的堆空间(如果需要的话),然后进行其他的operation.而拷贝函数不需要如此,因为对象此时还没有分配堆空间。 2.C++中有些重载运算符为什么要返回引用?...最后,我们回到我们最前面解释: 对于STL源码设计也是考虑模仿内置类型的行为,后置的++需要返回增加之前的对象,不需要返回新对象,所以直接返回对象的引用.

82440
领券