浅谈C++封装(期末考试版)(零基础勿入)

本文提到了那些知识点

1.cpp中的结构体和c中的结构体的区别。

2.cpp中的结构体和类的区别。

3.类的基本构成

4.编译器默认提供类的什么东西?哪些可以被重载?

5.权限有什么意义

6.深拷贝和重载赋值运算符的意义和方法

7.成员函数的类外实现和内联

8.内联和宏

9.this指针、成员函数和一般的全局函数的区别

10.类和static

11.类和const

12.指向类数据成员的指针

13.对象的存储模型

14.默认参数

15.作用域运算符如何记忆写在哪里?

16.多个类遇到不同情况的声明和实现顺序、友元

17.占位参数的应用场景

18.类内数据成员无法运用本身类为类型的原因

c++封装相关难点启蒙

1.谈一谈对类、结构体的基本认知

​ 从组成上来说,cpp中的结构体和c中的结构体并不相同,cpp中的struct和class区别不大,c中的struct只能包含属性,是属性的包装(不是封装而是打包),而cpp中的struct和class则是集成成员属性、方法、权限的一个封装体。

​ cpp中:struct 和class的唯一区别:不写权限时,默认为结构体的权限默认为public,而类则是private。

​ 类由两大部分构成:数据成员和成员函数,前者又叫做属性,后者又叫方 法。定义类时,默认把数据成员设置为私有权限–我们往往不希望用户对这些数据成员直接进 行操作,如果非要让用户进行操作,我们提供get,set这样的接口(公有的成员函数)对数据成员进行读写, 即用户和类的交互都是通过API接口来实现的。对成员函数,从用户的角度来说,使用最简洁的接口,而不是用自己不关心的业务逻辑层(设置为私有),是合理的,对程序员来说也是最安全的。

​ 成员函数分为构造函数、析构函数、一般的成员函数:一般来说,系统默认提供构造函数 的空实现、析构函数的空实现、拷贝构造函数、默认的赋值运算符四个东西。除析构函数以外,其他成员函数均可以被重载。

​ 深拷贝和重载赋值运算符的必要性和前提:当成员属性有指针类型时,我们要在堆为其开辟内存,也正因如此,必须手动提供析构函数释放内存。此外,必须重写拷贝构造和重载赋值运算符,进行深 拷贝,防止同一块内存二次释放。

​ 深拷贝的步骤:手动再次开辟一块堆区内存,并让自己的 指针属性指向那块内存,为了满足我们拷贝的初心,只把对象的值,拷贝过来,即把对方的堆 区内存的val拷贝到我这个新开辟的堆区的内存上,完成拷贝;而不是直接让我的指针指向人家的那块内存导致内存二次释放。重载赋值运算符也类似,不一样的只是自己本来有先释放干净再重新开辟。

​ 成员函数类外实现、内联、宏:类内的成员函数可以在类内声明类外定义,即用返回 类名::函数名(…){ } 的方式进行类外定义。至于为什么要类外定义,就不得不提到inline–内联函数,提到内联函 数,又不得不提宏定义了。宏定义不属于程序的一部分,可以说它是预处理的一部分,在编译 阶段,就完成了宏的替换,宏函数是直接替换到需要它的地方,而不是寻址式的函数调用,这 样就减少了开销。内联函数是一般函数前面加上关键字inline,这样就完成了类似于宏函数一 样的替换,而不需要调用,在某种情况下,可以减少开销,尽管我们平常用的很少,因为不至 于为了这点性能….对性能的要求不苛刻。类内直接给出定义就相当于默认在成员函数的前面加 上了inline,即默认为内联函数了。内联函数并不是适合任何的函数的,对于比较大的程序, 比如包括循环等在内的复杂逻辑,就不适合内联了。有时候为了避免默认内联,会放到类外去 定义。在多文件的情况下,有时候会专门开一个cpp文件专门为类的成员函数提供类外实现的 文件。

2.谈一谈this指针

​ 因为类内的方法都是存储在代码区的,也就是说不同对象都共享一 份函数体代码,如setA方法,如何区分是要设置哪个对象的A变量呢?这就需要一个参数,在 调用它的同时,隐式的将自己传入到这个方法内,因此所有类内成员函数之所以不同,之所以 可以用点来调用这个函数,就是因为这个函数比一般的函数多一个隐形的参数:类 * this;当某 一个对象调起的时候,就把这个对象的地址传入,就知道修改哪个对象的值了;另一个方面来 说,我们写的函数体内部引用的自身类的变量前面都藏着一个this->,而这个this其实就藏在 参数列表内。 原因的本质还是函数体放在了公共代码区。

3.谈一谈类和static

​ 关于static 先说静态的数据成员,静态的数据成员依附于类,不依附于对象,即一个对象对静态成员 做出的改变,其他对象也可以看到这种改变。因此,静态数据成员不能用构造函数进行初始 化,只能类内声明,类外定义。 额外补充一点,变量的存储类型有四种,auto、static、register、extern,这都是放在 声明里面的,而不是定义。 类外定义的格式:eg:int Person::cnt = 0;而一般的数据成员只可以类内声明;无需 类外初始化因为它们的初始化要靠构造函数来完成。 静态的成员函数和一般的成员函数的区别是:其目的是为了处理static的变量的,因为ta也 不依附于对象,不能直接对非静态的数据成员进行引用,因为不知道是哪个对象的。如果非要 用,前提是有一个对象存在才可以。这就是最大的区别,即不能对非静态的数据成员进行引 用。 static的东西可以通过对象调起,也可以直接通过类名进行调起。

4.谈一谈对象的存储模型

​ 空类只有一个字节,这个字节是占位置用的,一旦声明数据 成员,则这一个字节就不算了,类的内存大小取决于数据成员所占用的内存大小,成员函数和 数据成员分开存储,函数体放在公共代码区。而函数内定义的变量则不放在代码区,而是放在 栈区,除非是new出来的放在堆区。

5.谈一谈类和const

​ 关于常成员、常函数、常对象 常对象:const Person p(…);即在前面加上const构成常对象;常对象的特点是:必须 在定义时给出构造函数对其数据成员进行初始化,且一经构造,以后不可修改。常对象只能调 用常成员函数,常成员函数也不能调用非常成员函数,否则可能有间接改变数据成员的值的风 险。 常数据成员,在声明前加上const;const的数据成员必须通过构造函数的初始化列表进行 初始化,且一旦初始化,不可修改。 常函数,在声明(如果有的话)和定义的参数列表后面加const修饰符,表示这是一个常成 员函数,只有这种函数才有资格操作常对象,因为这样的话才能保证常对象的内容不被修改。 非常成员函数不能用来操作常对象。常函数内不可以发生任何修改的操作,哪怕是非常数据成 员也不可以在常函数内被修改。 总之,常对象的数据成员不可以被修改。常函数内不可以修改成员的值。只有常函数才可 以操作常对象。 注意:常对象只能调用常函数,并不意味着只有常对象才能调用常函数,所有对象都可以 调用常函数!!! 所有人都可以调常函数,但常对象只能调用常函数!

6.谈一谈指向类数据成员的指针

​ 指向特定类的数据成员的指针:存在着这样的一种指针,它们只能指向特定类的某种类型 的数据成员,要相给它赋值必须经过两道检查,首先要符合基本数据类型,然后必须符合特定 类。 eg:int Person::*p; 这是一个在main函数中声明的指针变量p,但是它比较特殊, 它的类型是int Person::* p只可以指向Person作用域内的int型的数据成员,不是Person类 内的int类型不可以被赋值给它。 在解引用时,可以通过对象来解引用,假如p = &ps.age; ps.*p就类似于ps.age;和 一般的指针相比,除了语法上的区别,只是对int指针进行了一定的限制而言。

7.谈一谈默认参数

​ 函数重载禁止用默认参数进行重载;会产生二义性;而且含有默认参数的变 量应该放在参数列表的最后。⭐默认参数一般放在函数定义处写,不要放在函数声明处,而且 只能放在一个地方,不能两个地方都有;。

8.谈一谈如何记忆作用域符号::写在什么位置

​ ① 构造函数 Person::Person(int a)… ②⭐析构函数Person::~Person()… 也就是说,~和类名是不分家的。关系更亲密 ③一般成员函数::void Person::ShowInfo(){…};紧紧跟在函数名之前,而不是整 个函数的前面,一般放在整个函数前面的都是一些关键字,比如friend,virtual…

9.关于多个类的声明顺序问题

​ 成员属性涉及到的类必须在此类前面进行声明;友元类或者成员友元函数所 在的类必须要在此类前定义;此外,类内声明数据成员时不允许进行初始化,一般的数据属性 只可以在构造函数内初始化。

细节整理:

  • 习惯:类内实现一般先public,后private,因为public对外的接口是用户所关心的部分;

  • int占位参数:一般用于区分重载运算符前置的++和后置的++;

  • 属性类型为自身相关类型?类内不允许数据成员的类型为本类,因为本类还没有写完,内存无法确定。但却可以是本类 的指针,单链表结点就很好的诠释了这一点;

  • 无参构造的学名叫做缺省构造函数,写题的时候问你会调用哪个,你直接把代码抄上去,不 要说第一个还是第二个。

  • 对象数组在被定义时,可以用大括号进行初始化,括号内可以用类名(…)的方式对前几个构 造,如果没给够,后面的调用缺省构造,如果不提供,那报错。

  • 析构函数也是被自动调用的,一般内部释放堆区的内存,它没有返回值,没有参数,不可以 被重载,但是可以声明为虚函数。顺序:先构造的后析构,因为在栈区!

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值