的说明 (1)我们通过自己的打印输出也可以看出来,这个时候是不能打印输出age,address的,因为他们不像public里面的name,他们一个是被保护的,一个是私有的,因此我们无法直接进行访问; 2. 变量是私有的,这个可以提高我们的代码的安全性;这个里面我们还自定义了一个新的函数对年龄进行加加操作,主函数里面没有调用这个函数之前age是20,调用这个函数以后就变成了21; 3.this指针指向语句里面的当前对象 ,这个时候name进行了接收,这个时候因为我们使用了this指针,所以编译器就可以正常识别,知道是把后面的参数赋值给前面的变量; 4.成员函数仅仅处理一个成员变量,处理多个成员变量需要独立的外部函数,对象可以作为函数的参数 (1)这段代码分别求了个人3门科目的平均分,以及3个人同一门科目的平均分; (2)getaverage是求单个人3门成绩的平均分。 (1)这个就是使用对象数组作为函数的参数;传递的是数组名,我们依然使用数组进行接收,这个和C语言里是类似的; (2)就相当于使用数组表示原来的s1,s2,s3,s4; (3)这个里面调用setstudent
1.类的默认成员函数 在 C++ 中,如果一个类没有显式定义某些成员函数,编译器会自动为该类生成默认的成员函数。 2.构造函数 2.1 构造函数的定义 在 C++ 中,构造函数是一种特殊的成员函数,用于初始化对象的数据成员。构造函数的名称必须与类名相同,并且没有返回类型,即使是 void 也不行。 2. 无返回值。 (返回值啥都不需要给,也不需要写void,不要纠结,C++规定如此) 3. 对象实例化时系统会自动调用对应的构造函数。 4. 构造函数可以重载。 2. 无参数无返回值。 (这里跟构造类似,也不需要加void) 3. 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。 4. 对象生命周期结束时,系统会自动调用析构函数。 一个局部域的多个对象,C++规定后定义的先析构。
接着上一章,这一次我将继续介绍C++类与对象的知识: 1.类的默认成员函数 用户没有显式实现,编译器自动生成的成员函数,即默认成员函数。 C++规定:对象在销毁时会自动调用析构函数,完成对象中资源(其实就是手动申请的空间资源,需要动态开辟空间,比如malloc之类的)的清理释放工作。 我们来说说第7个特点:⼀个局部域的多个对象,C++规定后定义的先析构 int main() { Date d1(2025,10,30); Date d2(2025,11,9); 1.4赋值运算符重载 1.4.1运算符重载 定义: 运算符重载是 C++ 面向对象特性的重要组成部分。 访问并且调用了这个函数,以实现d1 - d2; 第二种则是直接相减,d1 - d2 ,编译器会把这句表达式,按照C++标准规定的语法逻辑 翻译成 d1.operator-(d2) ,也就是显式调用,
构造函数的特点: 函数名就是类名 无返回值(返回值什么都不需要给,也不需要写void,C++规定) 类实例化对象时会自动调用对应的构造函数 如果类中没有显示的定义构造函数,则C++编译器会自动生成一个无参的默认构造函数 C++规定,对象销毁时自动调用析构函数,完成对对象中资源的清理释放工作。 C++规定自定义类型对象进行拷贝行为必须调用拷贝构造,所以这里自定义类型传值传参和传值返 回都会调用拷贝构造完成。 若未显式定义拷贝构造,编译器会自动生成拷贝构造函数。 d1); // Date d2 = d1; // 可以利用指针完成拷贝,但是不是拷贝构造,只是⼀个普通的构造 Date d5(&d1); // 传值传参 C++规定自定义类型对象进行拷贝行为必须调用拷贝构造 5.1 运算符重载 运算符重载的特点: 当运算符被用于类类型的对象时,C++语言允许我们通过运算符重载的形式指定新的含义。
一、六大默认成员函数 C++为了弥补C语言的不足,设置了6个默认成员函数 二、构造函数 2.1 概念 在我们学习数据结构的时候,我们总是要在使用一个对象前进行初始化,这似乎已经成为了一件无法改变的事情 对象生命周期结束时,C++编译系统系统自动调用析构函数 typedef int DataType; class Stack { public: Stack(size_t capacity = 3) 4.3 使用场景 1、使用已存在对象创建新对象 2、函数参数类型为类类型对象 3、函数返回值类型为类类型对象 为了提高程序效率,一般对象传参时,尽量使用引用类型,返回时根据实际场景,能用引用 但是C++中的*this指针是隐含的参数,我们没办法直接加,C++为了解决此类问题,规定当我们将const修饰放在成员函数后面的时候,默认就是将该成员函数隐藏的*this进行const修饰 将const 所以+=可以直接就操作,+却要重新创建一个类对象然后进行拷贝,再拷贝的对象上进行操作 注意事项: 1、+=和-=都是引用返回、不能用const修饰(改变原对象),返回值是类(支持连续操作) 2、+和-都是传值返回
2.构造函数 构造函数是特殊的成员函数。虽然名叫构造函数,但是它的主任务并不是开空间创建对象,而是对象实例化时初始化对象。 相当于Stack中的Init函数. ,C++中规定对象在销毁时会自动调用析构函数,完成对象中资源的清理和释放工作。 (3)C++规定自定义类型对象进行传值传参时必须调用拷贝构造,所以自定义类型进行传值传参和传值返回都会调用拷贝构造来完成。 (4)如果未显式写拷贝构造函数,编译器会自动生成拷贝构造函数。 +规定自定义类型对象进行拷贝行为必须调用拷贝构造,这里传值传参要调用拷贝构造 Date d2(d1); Date d2 = d1;//这两种写法都是可以的,也都是拷贝构造 return 0; } 5.赋值运算符重载 5.1 运算符重载 当运算符被用到类类型对象时,C++允许我们用运算符进行重载的形式指定新的定义。
C++随记(十)--类与对象(2) 1、 类的构造函数 类的数据成员是不能在声明类的时候初始化的!因为类不是一个实体,是一种抽象类型,并不占存储空间。 C++为我们提供了一个特殊的成员函数---类构造函数,专门用于构造新对象,来处理对象的初始化问题。 这个成员函数不需要用户来调用它,而是在建立对象的时候自动执行。 2、 析构函数 析构函数的作用与构造函数相反,析构函数并不是删除对象,而是在撤销对象占用的内存之前完成一些清理工作。析构函数无返回值,无函数类型,无任何参数。不能被重载。 (2)如果调用的是局部自动对象,则建立对象时调用构造函数。在函数调用结束,对象释放时调用析构函数。 (3)如果在函数中调用静态(static)局部对象,则只在程序第一次调用此函数建立对象时调用构造函数一次,函数调用结束时,对象并不释放,也不调用析构函数。
引述 2. 详述 2.1. 数据类型初始化 2.2. 类初始化 1. 引述 在C++中,学习类的第一课往往就是构造函数。根据构造函数的定义,构造函数式是用于初始化类对象的数据成员的。 2. 详述 2.1. 数据类型初始化 正如上一篇文章《面向对象编程(C++篇1)——引言》中提到的那样:类是抽象的自定义数据类型。 ,而赋值的含义则是把对象的当前值擦除,以一个新的值来代替。 以这个类对象中的数组数据成员data为例,假使这个数组的容量很大,其额外的一次赋值操作对于底层来说,是不可忽略的性能开销。 ImageEx() : imgWidth(200), imgHeight(100), bandCount(3), data{ 0, 1, 2
1、赋值运算符重载 1.1运算符重载 当运算符被用于类类型的对象时,C++允许我们通过运算符重载的形式指定新的定义。 C++规定类类型对象使用运算符时,必须转换成调用对应运算符重载,若没有对应的运算符重载,则会编译报错。 C++规定,后置++重载时,增加⼀个int形参,跟前置++构成函数重载,方便区分 重载<<和>>时,需要重载为全局函数,因为重载为成员函数,this指针默认抢占了第一个形参位置,第⼀个形参位置是左侧运算对象 ,再用这个临时对象拷贝构造aa2 //编译器遇到连续构造+拷贝构造->优化为直接构造 A aa2 = 2; aa2.Print(); A& raa1 = aa2; const A& raa2 如果你没有给缺省值,对于没有显示在初始化列表初始化的内置类型成员是否初始化取决于编译器,C++并没有规定。
1 赋值运算符重载 1.1运算符重载 在学习赋值运算符重载之前,我们先来介绍一下运算符重载: C++为了增加代码的可读性,引用了运算符重载的概念,运算符重载其实就是一个特殊一点点的函数,返回值,参数, 当我们比较一个数是否相等时候,我们直接: int a = 0; int b = 1; bool ret = a == b; 直接利用运算符比较就行,但是对于日期类的我们不能这样干,因为直接比较的都是内置类型,在C+ _year == d2._year && d1._month == d2._month && d1._day == d2. 这个经常在笔试选择题中出现 我们不能使用C++里面没有的符号来创建新的符号,因为没有实际意义,编译器也走不过去。 答案是不行的,因为全局重载函数要访问的话,类的成员变量一定要是公有的,不然就会报错: C++提供了三个解决方法: 1 提供这些成员的get和set 2 使用友元 3 重载成成员函数 这里着重介绍的是重载成成员函数
part1讲述了基于对象,part2则是在基于对象的基础上,建立类与类之间的联系,即面向对象编程以及面向对象设计。 主要讲述以下三点: Inheritance (继承) Composition(复合) Delegation (委托) 另外,我把补充内容中的对象模型放入到Part2,我觉得放入这里更加合适。 由此可见,C++动态绑定很棒,很强大。 :fy2_test(); return 0; } 输出结果: object model test: A::vfunc1() B::vfunc1() B::vfunc1() 面向对象的笔记到此结束 ,深深感受到了C++面向对象程序的power,fighting!
C++之类和对象(上) 本节目标 1. 面向过程和面向对象初步认识 2. 类的引入 3. 类的定义 4. 类的访问限定符及封装 4.1 访问限定符 限定域与类的区别 4.2 封装 5. C++是基于面向对象的,关注 的是 对象,将一件事情拆分成不同的对象,靠对象之间的交互完成。 2. 类的引入 C语言结构体中只能定义变量,在C++中,结构体内不仅可以定义变量,也可以定义函数。 : Date类中有 Init 与 Print 两个成员函数,函数体中没有关于不同对象的区分,那当d1调用 Init 函数时,该函数是如何知道应该设置d1对象,而不是设置d2对象呢? C++中通过引入this指针解决该问题,即:C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有“成员变量”的操作,都是通过该指针去访问 总结 这篇文章涉及的内容是C++类和对象的起始,对于类和对象,其中有许多难点,于是我想将它分成上中下三篇。我们一起进步!
0; 首先C++把类型分为了内置类型和自定义类型。 C++中引入了析构函数来完成与之相似的功能。 这会引发一个错误,导致程序崩溃: 原因是浅拷贝导致的,栈类对象st1内成员指针变量_array指向了一块动态开辟的空间,而栈类对象st2内成员指针变量_array也指向了栈st1指针成员_array _day; } 调用这个函数isEqual()即可比较: isEqual(d1, d2);//d1、d2是类对象 但这样不太直观,能不能像整型变量那样使用==运算符进行比较呢? _day; } 于是我们可以这样调用运算符==: d1==d2;//d1、d2是类对象 //operator==(d1, d2); 但是成员变量一般是私有的private,在类外时一般不能访问到类内的成员变量
C++先声明类类型,然后再定义对象 在C++中,声明了类类型后,定义对象有两种形式 1、class 类名 对象名 //把class和Student合起来作为一个类名,用来定义对象 class Student stu1,stu2; 2、类名 对象名 //直接用类名定义对象 Student stu1,stu2; 这两种方法是等效的,第1种方法是从C语言继承下来的,第2种方法是C++的特色,第2种方法更为简捷方便 //定义了两个Student类的对象stu1与stu2 C++不出现类名,直接定义对象 一般形式如下 class //class开头 无类名 { private: //声明私有部分 … … public: //声明公用部分 … … }stu1,stu2;//定义了两个Student类的对象stu1与stu2 在C++中,直接定义对象是合法的、允许的,但小林建议大家尽量不去用它 C++定义对象 | 对象举例 更多案例可以go公众号:C语言入门到精通
Markdown 画图工具 Processon 1,关于对象 从这篇博客开始真正介绍C++对象模型,前边BB了那么多没用的,终于开始了C++对模型的分析。 关于C++对象模型的介绍,我将根据《深度探索C++对象模型》这本书,其书中的每一章,对应一篇博客,博客内容为自己对这本书的理解和补充吧。 pd.init(&pd); } 1.2 class 需要指出的是,C++类的非static的成员函数都有一个隐式的参数,即this(class object *const this)指针(对象的首地址) (即链接时的多态)和虚继承(即多次出现在继承体系中的父类,在子类对象中有一个单一共享的实例,其最典型的是菱形继承) 另外,需要指出的是,C++中class和struct关键字都可以包含函数,其不同点在于 delete p; } class point的对象对应的内存布局 class point2d的对象对应的内存布局 通过对比point和point2d的对象内存布局,可知,如果父类中定义了虚函数,并且在子类中进行了重写
⼀元运算符有⼀个参数,⼆元 运算符有两个参数,⼆元运算符的左侧运算对象传给第⼀个参数,右侧运算对象传给第⼆个参数。 C++规定, 后置++重载时,增加⼀个int形参,跟前置++构成函数重载,⽅便区分。 2024, 7, 6); // 运算符重载函数可以显⽰调⽤ d1.operator==(d2); // 编译器会转换成 d1.operator==(d2); d1 == d2; // 编译器会转换成 ⻉赋值,这⾥要注意跟 拷⻉构造区分,拷⻉构造⽤于⼀个对象拷⻉初始化给另⼀个要创建的对象。 _day; } // d1 = d2表达式的返回对象应该为d1,也就是*this return *this; } void Print() { cout << _year << "-"
C和C++差别非常大。 C是面向过程的。 C++既可以面向过程,也可以面向对象,并且以面向对象为主。 为何要以面向对象为主呢?因为若只是面向过程,用C语言就行了,不用再劳心劳力再创造一种新的语言。 C++是一些聪明的程序员在C的基础上创造、发展起来的,与C语言最大的区别就是面向对象。 C语言的重点在于算法和数据结构,C程序的设计首要考虑的是如何通过一个过程,对输入进行运算处理得到输出。 而对于C++,首要考虑的是如何构造一个对象模型,让这个模型能够契合与之对应的问题域,这样就可以通过获取对象的状态信息得到输出或实现过程控制。 从这一点看,C++是面向对象编程(OOP)的。 C++还像C语言一样面向过程。 所以C++既是面向过程的语言 ,也是面向对象的语言。一般来说,用它的面向对象这方面。 以后会学到Java。Java不能面向过程,是完全面向对象的。 以狗吃屎为例,来说明面向过程和面向过对象的区别。 C语言:吃(狗,屎) 这里“吃”是函数名,“狗”和“屎”是参数。强调的是吃这一过程。 C++:狗.吃屎() 这里狗是对象,吃屎是狗的一个函数。
作为C++的核心单元,对象模型在编译器眼中是如何实现的?本文从几个基本理论模型出发,剖析实际。 深度探索C++对象模型 ---- 简单对象模型 对象存放若干slots,由slot指向实际成员。 多态:以public base class的指针或引用,寻址出一个derived class object 问题1:什么样的类需求此信息 答:定义虚函数的类 问题2:这样的类需求什么样的信息 答:对象的类型 例如,如果Derived继承自Base1和Base2基类,temp为已知Derived指针。 在派生类指针赋值给基类指针时编译器需要调整 Base2 * pbase2 =temp ? ---- C++对象模型 上述模型的Extension部分其实已经涵盖了部分对象模型的静态结构,而对象模型的生成与维护则更多见原书中的一系列章节。 Bjarne Stroustrup设计的C++对象模型从简单对象模型派生而来,对内存空间和存取时间做了优化。
最近在公司弄游戏开发,C++基础也不是特别好,所以就打算继续开始学习C++。 既然从头学习C++,就打算写一个系列教程。C++学习之路。 我是在边学习C++,边学习cocos2dx 3.X,白天时间不是很多, 先把C++系列写完再写coco2dx的教程。 希望对大家有帮助。 (可能基础知识不是很详细,对没有其他语言基础的人来说不是很友好,请见谅) 每个实体都可以看成一个对象。在C++中,对象的类型被称为类。 类代表了某一批对象的共性和特征。 类是对象的抽象,而对象是类的具体实现。 在C++中要使用一个类,首先要定义一个类。 定义类 定义类和声明结构体的结构是相似的。 对象成员的引用 程序中访问对象成员有以下三种方法: 1、通过对象名和成员访问运算符”.”来访问 2、通过指向对象的指针来访问 3、通过引用来访问 Student stu;
用类这种类型在物理内存中创建对象的过程,称为类实例化出对象。 2. 但是成员函数并没有保存在每个对象里面。 2. 所以计算类的大小时候,只计算成员变量占用的内存,并不计算成员函数占用的内存。 3. C++规定类实例化的对象也要符合内存对齐的规则。 4. 构造函数是一个特殊的成员函数,其主要任务并不是开空间创建对象,而是对象实例化时初始化对象。 2. 析构函数与构造函数功能相反,构造函数不是用来创建对象,析构函数也不是用来完成对象本身的销毁。 2. C++规定对象在销毁时会自动调用析构函数,完成对象中资源的清理释放工作。 ⼀个局部域的多个对象,C++规定后定义的对象先析构。