C++类和对象

1、面向程序设计的基本特点:抽象、继承、封装、多态

2、①类的成员之间可以相互直接访问

②类成员默认的访问权限是私有

③类的私有特性成员在类外部只能通过类的公有成员函数或友元函数间接访问。不能在类外或派生类中使用

3、在类外部实现类的成员函数时,需要借助类名来限定成员函数

4、当类中存在指针成员时,如果仍需要实现对象之间的赋值,在定义类时应当为类重新定义赋值运算符重载函数

5、使用分号结束类的定义语句

6、构造函数和析构函数没有返回值

7、不能用关键字auto、register、extern将成员(函数成员返回值可以用auto声明)说明为自动类型、寄存器类型或外部类型。可以用关键字static将成员说明为静态类型,其意义为该成员属于类的所有对象共有。

8、非const 的静态数据成员要在类外定义和初始化,const static的数据成员必须在类里初始化

9、构造函数和析构函数(由系统执行,在函数中不可显式地调用它们)

①只要调用类新建对象,就会自动调用构造函数

②**构造函数:**建立对象时对对象的数据成员进行初始化;与类同名的特殊成员函数;没有return语句;没有返回值,不使用void;可以有多个,带参及无参均可(构造函数可以被重载);构造函数可以是内联函数

**析构函数:**对象声明周期结束时回收对象;与类同名,在其前面加上字符"~";没有返回值;只有一个,无参

③先构造的后析构,后构造的先析构。(栈的性质)

10、参数化列表

①使用初始化列表对成员进行初始化,比在构造函数体中用赋值语句对成员赋值的效率更高。

②初始化列表使用条件:不需要进行合法性判别可以直接赋值

③列表中成员的初始化顺序由定义类时这些成员的说明顺序决定。列表中的成员初始化完成后,再执行构造函数体中的语句对其他成员进行初始化。

11、下面两个都是默认构造函数,如果同时在类中出现,将产生编译错误:

①Clock(); ②Clock(int newH =0, int newM= 0, int newS=0);

【默认构造函数可以是没有参数的构造函数,也可以是有参数且各个参数均有默认值的构造函数。但一个类中最多只能有一个默认的构造函数】

12、默认构造函数

①C++规定,每个类必须有构造函数

②默认构造函数只是在形式上保证创建对象时必须有构造函数(默认构造函数仅仅用来生成对象而不初始化对象)

③一旦写了一个构造函数,系统就不再提供默认的构造函数

④编译器有时不能为某些类合成默认的构造函数:eg:如果类中包含一个其他类型的成员,并且这个类没有默认构造函数,那么编译器就无法初始化该成员。

13、委托构造函数(类初始化类):一个委托构造函数使用它所属类的其他构造函数执行它自己的初始化过程

14、复制构造函数(对象初始化对象),其形参是本类对象的引用

复制构造函数的参数一般也应该采用常引用传递。

①系统会在必要时自动生成一个隐含的复制构造函数(这个隐含的复制构造函数的作用是,把初始值对象的每个数据成员的值都复制到新建的对象中)

Point是一个类:Point(Point &p);//复制构造函数

Point::Point(Point &p){//x,y为Point的数据成员

复制代码
x=p.x;

y=p.y;

}

在类内使用本类对象去初始化时,需要传引用

②复制构造函数被调用的三种条件:

条件一:当用类的一个对象去初始化该类的另一个对象时

条件二:(只有把对象用值传递时,才会调用复制构造函数,如果是传递引用,则不会调用复制构造函数。因此,传递比较大的对象时,传引用会比传值效率高很多

【注】主函数f返回时,为删除形参对象p,执行析构函数。主函数执行结束时,为删除对象a,执行析构函数。

条件三:如果函数的返回值是类的对象,函数执行完成返回调用者时

【注】a是g()的局部对象,离开创建它的函数g()以后就消亡了。在面对返回值是类的对象这种情况时,编译系统会在主函数中创建一个无名的临时对象,该临时对象的生存期只在函数所处的表达式中,也就是表达式b=g()中。执行语句return a时,实际上是复制构造函数将a的值复制到临时对象中。函数g运行结束时对象a完全消失,但临时对象会存在于表达式"b=g()"中,计算完这个表达式后,临时对象的使命也就完成了,该临时对象便自动消失。

++i与i++

③赋值运算符(=)作用于一个已存在的对象,而复制构造函数会创建一个新的对象

15、当类的数据成员中有指针类型时,默认的复制构造函数实现的只能是浅复制。浅复制会带来数据安全方面的隐患,要实现正确的复制,也就是深复制,必须编写复制构造函数。

16、析构函数

①析构函数是在对象的生存期即将结束的时刻被自动调用的。它的调用完成之后,对象也就消失了,相应的内存空间也被释放。

②析构函数不接受任何参数,但可以是虚函数。

  • 将基类析构函数说明为虚析构函数,让所有派生类的析构函数自动成为虚析构函数
  • 用基类指针建立派生类的动态对象,且显式调用delete运算时,系统会调用相应类的析构函数,删除派生类对象,同时删除派生类对象从基类继承的部分

③析构函数没有返回值,不可以被重载,这是析构函数和构造函数的一个区别

④动态内存需要由用户主动释放,析构函数不会自动释放动态内存

17、在创建一个组合类的对象时,不仅它自身的构造函数的函数体将被执行,而且还将调用其内嵌对象的构造函数,这时构造函数的调用顺序如下:

①调用内嵌对象的构造函数,调用顺序按照内嵌对象在组合类的定义中出现的次序。注意,内嵌对象在构造函数的初始化列表中出现的顺序与内嵌对象构造函数的调用顺序无关。

②执行本类构造函数的函数体

18、移动构造函数(本质:资源权限的转移)

①左值引用与右值引用:(左值可以取地址,右值不可以取地址)

  • 对持久存在变量的引用称为左值引用,用&表示
  • 对短暂存在可被移动的右值的引用称为右值引用,用&&表示

    ②std::move()能把左值强制转换为右值,继而可以通过右值引用使用该值,以用于移动语义

    move函数告诉编译器变量n转换为右值来使用,承诺除对n重新赋值或者销毁它意外,将不再通过rr_n右值引用以外的方式使用它。

③移动构造函数传参使用&&右值引用,避免发生复制构造。移动构造函数的参数为该类对象的右值引用,在构造中移动源对象资源,构造后源对象不再指向被移动的资源,源对象可重新赋值或被销毁。

使用移动构造函数直接挪用已有右值对象的成员资源,因此配合move函数使用完成新对象移动构造。上例有参构造函数中,局部string类型变量因用来初始化类内string成员后无其他使用,也可通过move将其转为右值移动来避免复制。需要注意的是,移动构造函数不会分配新资源新内存,因此理论上不会报错,为配合编译器异常捕获机制,需要声明notexcept表明函数不抛出异常。

19、default和delete函数

①default

  • 不需要提供默认构造函数时,则不生成默认构造函数,提升效率。
  • 使用default,可以让编译器合成简单的无参默认构造函数和复制构造函数

    ②delete:除析构函数外,用户都可以指定为delete删除掉

    20、类的组合

①类的组合描述的是一个类内嵌其他类的对象作为成员的情况,它们之间的关系是一种包含与被包含的关系。

②在创建对象时既要对本类的基本类型数据成员进行初始化,又要对内嵌对象成员进行初始化。

③组合类构造函数定义的一般形式为

④创建组合类对象时构造函数的调用顺序

(1)调用内嵌对象的构造函数,调用顺序按照内嵌对象在组合类的定义中出现的次序。注意,内嵌对象在构造函数的初始化列表中出现的顺序与内嵌对象构造函数的调用顺序无关。

(2)执行本类构造函数的函数体。

【注1】如果有些内嵌对象没有出现在构造函数的初始化列表中,那么在第(1)步中,该内嵌对象的默认构造函数将被执行。

【注2】有些数据成员的初始化,必须在构造函数的初始化列表中进行,这些数据成员包括两类,一类是那些没有默认构造函数的内嵌对象(这类对象初始化时必须提供参数);另一类是引用类型的数据成员,因为引用型变量必须在初始化时绑定引用的对象。

⑤析构函数的调用执行顺序与构造函数刚好相反

析构函数的函数体被完毕后,内嵌对象的析构函数将被一一执行,这些内嵌对象的析构函数调用顺序与它们在组合类的定义中出现的次序刚好相反。

⑥组合类的复制构造函数

如果要为组合类编写复制构造函数,则需要为内嵌对象成员的复制构造函数传递参数。假设C类中包含B类的对象b作为成员,C类的复制构造函数形式如下:

⑦含内嵌对象的类的初始化(参数都传进去,一部分用来初始化内嵌对象)

21、前向引用声明

尽管使用了前向引用声明,但是在提供一个完整的类定义之前,不能定义该类的对象,也不能在内联成员函数中使用该类的对象。

22、深复制和浅复制

①浅复制:只是将指针改变,并没有实现真的赋值,两个变量占用相同的内存,容易造成严重的错误

23、UML

①在UML中,静态数据成员是通过在数据成员下方添加下划线来表示

②在UML中,静态函数成员是通过在函数成员添加< >构造型来表征

③在UML中,友元函数是通过在成员函数前方添加< >构造型来表征

④在UML中,两个类之间的友元关系是通过< >构造型依赖来表征

⑤在UML中,常成员函数是通过在成员函数前添加< >构造型来表征

⑥在UML中,常数据成员是通过在数据成员类型前添加const类型来表征

⑦在UML中,一般的虚函数是通过在成员函数前添加< >构造型来表示

⑧在UML中,纯虚函数也称为抽象函数,它是通过斜体书写函数名称并在前面添加< >构造型来表示

⑨在UML中,抽象类是通过斜体书写类名称来表示。

⑩在UML中对类模板的实例化是通过使用绑定(< >)构造型的依赖关系表示的。

24、结构体(struct)

①结构体是一种特殊的类。结构体中未定义任何访问控制属性的成员,其访问控制属性为public

②引入结构体是为了兼容C

25、联合体(union)

①联合体是一种特殊的类,它的默认访问控制权限是public

②联合体的全部数据成员共享一组内存单元,因此一个联合体变量的成员同时至多只有一个是有意义的

③联合体不能继承,因而也不支持多态

④联合体可以不声明名称,称为无名联合体,可以由成员项的名字直接访问。

26、枚举类型(enum):将所有可能的值一一列举出来

①eumu Weekday{SUN,MON,TUE,WED,THU,FRI,SAT};

②枚举类型应用说明

  • 对枚举元素按常量处理,不能对它们赋值。

    SUN=0;//错误,枚举类型不能赋值

  • 枚举元素具有默认值,它们依次为:0,1,2

  • 可以在声明的时另行定义枚举元素的值

    eumu Weekday{SUN=7,MON=1,TUE,WED,THU,FRI,SAT};

    相应的,TUE=2,后面依次+1

    27、protected和private的区别:protected在继承和派生时派生类的成员函数可以访问基类的保护成员

相关推荐
风归去2 天前
C++数据的共享和保护
c++面向对象