1、类内的成员函数都有一个隐式的形参this指针,在通过对象调用成员函数时,将当前对象的地址作为实参传递给this。因为this的目的总是指向“这个”对象,所以this是一个常量指针,不允许改变this中保存的地址。

2、默认情况下,this的类型是指向类类型非常量版本的常量指针。例如,在Sales_data成员函数中,this的类型是Sales_data *cost。尽管this是隐式的,但它仍然需要遵守初始化规则,此时,this不能绑定到常量对象。这一情况也就使得我们不能在一个常量对象上调用普通成员函数。如果在成员函数体内不改变当前对象,为了提高函数的灵活性,则应该把this声明成指向常量对象的常量指针,方法是在成员变量参数列表后面加上cosnt。这样的函数被称为常量成员函数,在常量成员函数内不能改变调用它的对象的内容。

3、默认情况下,拷贝类的对象,其实拷贝的是对象的数据成员。

4、构造函数不能被声明为const的。当我们创建类的一个const对象时,直到构造函数完成初始化过程,对象才能真正取得其“常量”属性。因此,构造函数在const对象的构造过程中可以向其写值。

5、编译器只有在发现我们没有定义任何构造函数的情况下才会生成吗默认构造函数。一旦我们定义了一些其他的构造函数,除非我们显示的定义默认构造函数,否则类是没有默认构造函数的。

6、含有内置类型或复合类型成员的类,应该在类内初始化这些成员,或者显示定义默认构造函数,否则这些成员的初始值将是未定义的。

7、参数列表为空的构造函数为默认构造函数,在形参列表后面加上=default可以要求编译器生成构造函数,即用它来代替空的构造函数体。=default既可以在类内部也可以写在类外部,在类内部时默认为内联的,在类外部为非内联。

8、没有出现在构造函数初始值列表中的成员,将通过类内初始值初始化或者默认初始化。

9、友元的声明只能出现在类定义的内部,但是在类内出现的具体位置不限。友元不是类的成员,也不受它所在区域访问控制级别的约束。一般来说最好在类定义开始或结束前的位置集中声明友元。

10、友元的声明仅仅指定了访问的权限,而非一个通常意义上的函数声明。如果我们希望类的用户能够调用友元函数,那么我们必须在友元声明之外再专门对函数进行一次声明。为了使友元对类的用户可见,我们通常把友元的声明与类本身放置在同一个头文件中(类的外部)。

11、类可以自定义某种类型在类中的别名,由类定义的类型名字和其他成员一样存在访问限制。用来定义类型的成员必须先定义后使用,因此类型成员通常出现在类开始的地方。

12、我们可以在类的内部把inline作为声明的一部分显示地声明成员函数,也能在类的外部用inline关键字修饰函数的定义。虽然我们无须在声明和定义的地方同时说明inline,但这样做是合法的,不过最好只在类外部定义的地方说明inline这样可以使类更容易理解。和我们在头文件中定义inline函数的原因一样,inline成员函数也应该与相应的类定义在同一个头文件中。

13、用mutable关键字声明的数据成员为可变数据成员,一个可变数据成员永远不会是const,即使它是const对象的成员,因此,一个const成员函数可以改变可变成员你的值。

14、类内初始值必须使用=的初始化形式,或者花括号括起来的直接初始化形式。

15、一个const成员函数如果以引用的形式返回*this,那么它的返回类型将是常量引用。

16、在类的声明之后定义之前,它是一个不完全类型。不完全类型只能在非常有限的情境下使用:可以定义指向这种类型的指针或引用,也可以声明(但是不能定义)以不完全类型作为参数或返回类型的函数。

17、因为只有当类全部完成后类才算被定义,所以一个类的成员类型不能是该类自己。然而,一旦一个类的名字出现后,它就被认为是声明过了(但尚未定义),因此类允许包含指向它自身类型的指针或引用。

18、每个类负责控制自己的友元类或友元函数,友元关系不存在传递性。

19、如果将另一个类的成员函数声明成本类的友元,那么必须按如下顺序设计程序:(1)先声明另一个类的成员函数,不能定义。(2)声明本类。(3)定义本类,包括对另一个类成员函数的友元声明(声明友元时应该用另一个类的名字和::来修饰该成员函数)。(4)定义另一个类的被指定为本类友元的成员函数。

20、尽管重载函数的名字相同,但它们仍然是不同的函数。如果一个类想把重载函数声明为友元,那么需要对每一个重载的函数都声明一次友元。否则,只有声明了友元的函数才可以访问该类的私有成员。

21、类和非成员函数的声明不是必须出现在它们的友元声明之前。就算在类的内部定义该函数,也必须在类的外部进行声明。

22、在类的外面定义类的成员函数需要用类名和::限定,类名之后出现的类内的成员无需再用类名修饰可以直接使用,此处类名之后指的是函数的参数列表和函数体,但是不包括函数的返回类型,如果函数的返回类型是类内定义的一种类型,则必须也用类名和::来限定。

23、类的定义分两步处理:(1)编译成员的声明。(2)直到类全部可见后才处理函数体。注意只是函数体,不包括返回类型和参数列表。如果成员函数定义在类内,则函数体内出现的成员可以正常访问,但是返回类型或者参数列表中出现的成员必须在该成员函数之前声明,否则编译器将跳出该类,在更外层的范围内查找同名的类型或者变量,如果外层查找不到则报错。

24、一般来说内层作用域可以重新定义外层作用域中的名字。即使改名字在内层作用域中使用过。然而在类中,如果成员使用了外层作用域中的某个名字,而改名字代表一种类型,则类不能在之后重新定义该名字。类型名的定义通常出现在类的开始处,这样就能确保左右使用该类型的成员都出现在类型名的定义之后。

25、成员函数内查找名字的顺序是(1)在函数内部查找(2)在类内部查找(3)在类外查找。如果类内的名字被函数内部相同的名字隐藏了,那么可以通过类名::或者this->来指定。如果类外的名字被隐藏了,那么可以通过::来指定。

26、类成员直接初始化和先定义再赋值的区别:如果类成员是const或者引用,或者属于某个类类型,但是该类没有提供默认构造函数的话,就会出错。

27、成员的初始化顺序与它们在类中的出现顺序一致,与构造函数初始化列表中的顺序无关。

28、如果一个构造函数为所有参数都提供了默认实参,则它实际上也定义了默认构造函数。

29、当一个构造函数委托给另一个构造函数时,受委托的构造函数的初始值列表和函数体被依次执行,然后控制权才会交还给委托者的函数体。

30、能通过一个实参调用的构造函数定义了一条从构造函数的参数类型向类类型隐式转换的规则。即在需要类类型的地方我们可以传递一个类构造函数所需要的类型的实参,这个实参会隐式的转换为类类型的对象。只允许一步类类型的转换。在含有一个参数的构造函数声明前加上explicit关键字可以避免隐式类类型转换。explicit构造函数只能用于直接初始化不能用于拷贝初始化(即用=的初始化)。尽管explicit不允许隐式转换,但是我们可以使用"static_cat<类类型> explicit构造函数参数类型的实参"这种形式来进行显示转换。

31、类的静态成员函数不能是const的,也不能在函数体内使用this指针。虽然静态成员不属于类的某个对象,但是依然可以使用类的对象、引用或指针来访问静态成员。

32、因为静态数据成员不属于类的任何一个对象,所以它们并不是在创建类的对象时被定义的,这意味着它们不是由类的构造函数初始化的。而且一般来说,我们不能在类的内部初始化静态成员。相反的,必须在类的外部定义和初始化每个静态成员。静态数据成员定义在任何函数之外。定义的方式为:类型名 类名::变量名 = 初始化值。例如int A::i=3;。要想确保对象只定义一次,最好的办法是把静态数据成员的定义和其他非内联函数的定义放在同一个文件中。如果静态数据成员是字面值常量类型的constexpr,则可以在类内定义,且其初始值必须是常量表达式。如果某个静态成员的应用场景仅限于编译器可以替换它的值的情况,则一个初始化的const或constexpr static不需要分别定义。相反,如果我们将它用于值不能被替换的场景中,则该成员必须有一条定义语句。即使一个常量静态成员在类内部初始化了,通常情况下也应该在类的外部定义一下该成员。

33、静态数据成员可以是不完全类型,特别的静态数据成员可以就是它所属的类类型。而非静态数据成员则受到限制,只能声明成它所属类的指针或引用。

posted @ 2022-12-11 21:10  许卡文迪  阅读(196)  评论(0编辑  收藏  举报