类的基础知识

1、定义抽象数据类型
类的基本思想是数据抽象(接口——用户能执行的操作 实现)和封装(接口和实现的分离)
成员函数的声明必须在类的内部,但定义既可以在内部也可以在外部,作为接口组成部分的非成员函数,定义和声明都在类的外部 定义在类内部的函数时隐式的inline函数
定义成员函数:
引入this:当调用成员函数时,其实是在替某个对象调用它,成员函数通过名为this的额外的隐式参数访问调用他的对象Sales::isbn(&total)->把对象的地址传给this指针
当调用一个成员函数是,用请求该函数的对象地址初始化为this 在成员函数内部,任何对类成员的访问都被看做是this的隐式引用,相当于写了this. 因此不能用名为this的形参和变量,我们当然也可以在成员函数内部使用this 因为this总是指向这个对象,因此是一个常量指针,不能改变this中保存的地址
引入const成员函数:默认情况下this的类型是Sales *const,因此不能把他绑定到一个常量对象上,也就是说不能再常量对象上调用普通成员函数 因为this不会出现在参数列表中,因此把const放在成员函数的参数列表之后就相当于修饰this,我们也不允许定义自己的this指针
常量对象以及常量对象的引用或指针都只能调用常量成员函数
类作用域和成员函数:即使成员变量出现在成员函数之后也是可以使用它的,因为编译器会先编译成员的声明才轮到函数体
类外部成员函数的定义必须与类内的声明一致,且函数名要包含所属的类名(用作用域表达 Sales::avg())当编译器看到函数名时,就知道剩下的代码是在类的作用域之内,因此变量也就可以直接使用
定义返回this对象的函数:为什么不能直接返回类型而要返回引用呢?? 对象是可以拷贝的,如果不返回引用返回的就是拷贝的对象,如果是引用就是同一个对象
定义类相关的非成员函数:尽管这些函数的操作从概念上属于类的接口的组成部分,他他们实际上不属于类 为什么print和read是非成员函数? 如果非成员函数是类的接口的组成部分,那这些函数的声明应该与类声明(不是定义)在同一个头文件中
构造函数:构造函数没有返回类型,名字与类名一样。构造函数不能被声明为const ,因为只有完成构造函数初始化过程,对象才能获得const属性 合成的默认构造函数如果类内有初始值就用初始值,如果没有就默认初始化,就可能会有未定义的问题 默认构造函数只要没有形参就行 当类中没有生命任何构造函数时,编译器才会生成合成默认构造函数 如果类中包含了其他类的成员而且他没有默认构造函数,那编译器就会出问题 Sales() = default = default就让默认构造函数和合成的默认构造函数一样,= default既可以在类的内部和外部,在内部则默认构造函数就是inline,在外部就不是inline
构造函数初始值列表: 构造函数初始值是成员名字的一个列表,每个名字后面紧跟括号括起来的成员初始值 就是:和{}之间的部分,成员名字(值) ,成员之间用,分开 如果构造函数只用赋值的话函数体可以为空,当然也可以在{}中进行初始化
问题: p238???为什么是0?因为他构造函数写了是0.。。 如果有有类内初始值也有构造函数听谁的?听构造函数的 初始值列表不同能是不同的构造函数吗?应该不能吧 初始值列表和函数体都对某个东西赋值?对的
类外部定义构造函数:我们也需要写作用域,也不用返回值 正常写就行
如果我们不主动定义的话,编译器会帮我们合成拷贝、赋值和销毁操作 但对于有些类这样不行p239
如果类包含有内置类型或者复合类型的成员,则只有当这些成员全都被赋予类内初始值时,这个类才适合合成默认构造函数

2、访问控制与封装
访问说明符:public private(public在整个程序被访问,private只能被类的成员函数访问)有效范围是出现下一个访问说明符或到类的结尾处 struct默认是public class默认是private 哪能return private么??我在网上搜答案的时候看到大部分回答都是在类内部创建一个接口 这不就和java里的一样么,当然可以了
友元:允许其他类或者函数访问private成员,只要在要访问的类或函数(注意不是被访问)加上friend即可 友元声明只能出现在类定义的内部,位置不限,但一般都在开头 友元的声明(仅仅是友元的声明)仅仅制定了访问权限而非通常意义的函数声明,如果希望类的用户能调用某个友元函数,需要在友元声明之外再对函数进行声明 友元如何对类的用户可见??p242

3、类的其他特性
7.3.1没看
返回this成员函数:函数返回值是个对象的引用相当于lll.s()本事就是一个对象(返回的和调用的是同一个),它可以接着调用其他函数,而且这些对象都是同一个 如果返回的不是引用而是对象,调用的和返回的就不是一个东西,只是被拷贝了而已
从const成员函数返回
this:this是const对象,返回值类型应该是const对象的引用 如果一个const成员函数以引用的形式返回this那么他的返回类型是常量引用, 那调用这个函数的对象就gg了么??没有把,应该只是赋值的不能修改了
基于const的重载:成员函数是否为const可以进行重载,跟指针参数是否指向const重载一样 成员调用成员时,this在其中传递,普通函数中调用const函数,this会被隐式的转换为const,普通函数的this还是那个this,不会因为传的时候转换了就发生改变(每个函数中的this都不一定一样,就是一个类有好多this而不只有一个)
类类型:每个类定义了唯一的类型,即使两个类的成员完全一样,他们也是不同的类型,所以赋值时不可能的
类的声明:仅仅是声明而没有定义,是一个不完全类型,只允许定义指向这种类型的指针和引用,也可以声明但不能定义以不完全类型作为参数或返回值的函数,我们不能创建他的对象(因为不知道要多大的空间)和用引用和指针访问成员
直到类被定义后数据成员才能被声明为这种类型,因此,一个类的成员不能是他自己,然而一旦类的名字出现后就被认为是声明过了,因此类可以包含指向它自身类型的引用或指针 那后面定义好之后可以用么??应该改可以把
友元再探: 类可以把其他类定义成友元,也可以把定义过的类的成员函数定义为友元 friend class …; friend void Window::clear();clear函数必须在screen类之前被声明
如果定义了友元类,那友元类的成员函数可以访问类中包括非public成员在内的所有成员 友元不具有传递性,比如A可访问B,B可访问C,但A不能访问C
如果令成员函数作为友元,需要用namespace指明这个成员函数属于哪个类, 比如window中的clear函数要访问screen类,要先定义window类,声明clear函数但不能定义它,接下来定义screen且声明友元,然后才能定义clear (只能使用已经写过的,不可能还没写就让你用)顺序只能是这样
友元声明及作用域:类和非成员函数的声明不是必须要在他们的友元声明之前,即使友元函数定义在类的内部,在声明函数原型之前都不能使用这个函数,类中的函数也不能???不能

4、类的作用域
在类的作用域外对于类类型成员要使用作用域运算符访问??如果成员在类外定义好了呢
作用域和定义在类外部的成员:一个类就是一个作用域,我们在外部定义成员函数加上类名就是在类的作用域之内了,如果返回类型也是类中的那也要加上作用域 那这样的话名字还要加么???
名字查找与类的作用域:一般的名字查找:现在所在块中寻找声明语句,只考虑在名字的使用之前出现的(上面的)声明,如果没有,继续在外层作用域查找,最终如果没找到,报错 什么时候能定义相同名字的东西呢???见下
但对于类内部的成员函数,不太一样 因为类的定义分两步,先编译类中全部声明,在处理成员函数的定义,因此成员函数可以使用类中定义的任何名字,两阶段处理只适用于成员函数中使用名字,声明中使用的名字包括返回类型,和参数列表中使用名字都必须在使用前就有,编译器指挥往前面找,即使后面有的话也不行,会在外层继续找
一般来说,内层作用域可以重新定义外层作用域中的名字,即使该名字已经在内层作用域中使用过,然而在类中如果成员使用了外层作用域中的某个名字,而该名字代表一种类型,那么类不能再之后重新定义该名字,即使重新定义与原来相同也不行
成员定义中的普通块作用域的名字查找:成员函数内找名字:现在成员函数作用域内找,只有之前的,如果成员函数内没有,就去类里找,招式所有成员都可以,上下都行,类里也没有,就去函数定义之前的作用域找 一般只能在上面找,除了一些特殊情况
类作用域之后,在外围的作用域中查找:如果内部和外部上面都有height,要访问外面那个,用::height
当成员定义在类的外部时,名字查找的第三步不仅要考虑类定义之前的全局作用域中的声明,还要考虑在成员函数定义之前的全局作用域中的声明
友元在类内定义一定要在类外声明才能使用

5、构造函数再探
构造函数初始值列表:如果没有在初始值列表中显示初始化成员,则该成员在构造函数体之前执行默认初始化 一个是初始化,一个是赋值
但有时成员是cosnt或者引用或者属于某种类类型但该类没有默认构造函数,那必须要初始化 一般初始化列表的顺序无所谓,但如果一个变量是用另一个变量初始化的话就有所谓了 如果一个构造函数为所有参数都提供了默认实参,那他实际上也定义了默认构造函数
委托构造函数:使用类中的其他构造函数执行自己的初始化过程 在委托构造函数内,初始值列表只有一个唯一入口,就是类名本身,类名后括号的参数列表必须与另一个构造函数匹配 受委托的构造函数的初始值列表和函数体依次执行
7.5.3没看完 Sales obj()是一个函数而不是对象,所以想用默认构造函数初始化对象,就把括号去了就行
隐式类类型转换:可以通过一个是惨调用的构造函数定义了一条从构造函数的参数类型向类类型隐式转换的规则 但是编译器只会自动的执行一部类型转换,“99999” -> string -> Sales就是错的 p264末尾??? 抑制构造函数定义隐式转换,只要加explicit就行,只能用于只有一个实参的构造函数,只能在类内声明时使用,类外定义时不能重复,如果被explicit了就不能Sales item = string了
当我们用explicit声明构造函数时,他只能以直接初始化的形式使用,而且编译器不会在自动转换的过程中使用该构造函数
我们不能用explicit的构造函数隐式转换,但是可以用于显示强制类型转换,但不管是显示还是隐式都只是一个临时对象,是临时量
string(const char*)不是explicit,接受容量参数的vector构造函数是explicit的
7.5.5 7.5.6没看

6、类的静态成员
声明静态成员:类的静态成员存在于任何对象之外,对象中不包含任何与静态数据成员有关的数据,相当于被所有对象共享,静态成员函数不包含this指针,函数不能被声明从const,也不能再函数体内使用this,这点既适用于this的显示使用,也适用于调用非静态成员的隐式使用
使用静态成员:用作用域访问,也可以使用类的对象和引用和指针来访问,成员函数不用通过作用域运算符就能直接使用静态成员
定义静态成员:既可以在类的内部也可以在外部定义静态成员函数,在外部定义是不能重复static关键字,也是必须要加上类名作用域
我们必须在类的外部定义和初始化每个静态数据成员,和在类外定义成员函数差不多,要有类名作用域,也不用加static,每个静态数据成员只能定义一次,也可以使用类的私有成员
静态成员的类内初始化:通常来说类的静态成员不应该在类内初始化,但我们可以为静态成员提供const整数类型的类内初始值,但要求静态成员必须是字面值常量类型,初始值必须是常量表达式,因为成员本身就是常量表达式,比如可以用初始化了的静态数据成员指定数组的维度,如果静态成员仅仅应用于编译器可以替换他的值的情况,则不需要再类外面专门定义这个这个变量,其他时候都必须要定义 没太看懂?? 到底变量的啥算是定义??
静态数据成员的类型可以就是他所属的类类型(不完全类型),而非静态数据成员受到限制,只能声明所属类的引用或指针
另一个区别就是可以用静态成员作为默认实参

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值