设为首页 加入收藏

TOP

C++类的相关问题、构造函数与析构函数、复制构造函数实例讲解(一)
2018-02-24 09:52:48 】 浏览:304
Tags:相关 问题 构造 函数 复制 实例 讲解

面向对象的基本任务是描述对象并对对象进行归类总结。类类型与int类型一样,也没有任何内存分配。类的属性和对外接口是类定义的重点和难点,原则是尽量让内部操作私有化,提供简单易用的接口函数。

1、类的相关问题

在定义类的数据成员时,不能像定义变量一样进行初始化,若在定义时未指明访问限定符,默认为private;

在定义类的方法时,若方法中不用修改类的数据成员,则最好在方法声明的最后使用const关键字,表示用户不能在此方法中修改类的数据成员。若类中包含指针成员,在const方法中不可以重新为指针赋值,但可以修改指针所指向的地址中的数据。

类中,除静态成员可以直接访问外,其它成员是通过对象来实现访问的。在定义类时并没有分配存储空间,只有当实例化对象时,才分配存储空间。也可以将类对象声明为一个指针,并使用 ?new运算符为其分配内存,如下所示:

image.png

若将类对象声明为常量指针,则只能调用类中的常量方法。

2、构造函数与析构函数

每个类都有构造函数与析构函数,构造函数在定义对象时被调用,析构函数在对象释放时被调用。构造函数负责类对象生成之前的初始化,析构函数负责对象销毁后的处理。

构造函数没有返回值,若用户没有提供构造函数和析构函数,则系统使用默认的构造析构函数。一个类可以包含多个构造函数,各函数通过重载来进行区分,下面是指针调用参数构造函数进行初始化:

image.png

类体中定义的数据成员不能初始化,故类中初始化只能借助构造函数的初始化列表实现。类成员函数,若在类体中定义,函数前即使没有使用inline,该成员函数也被认为是内联函数。

析构函数没有返回值,也没有参数,故不能重载。

3、复制构造函数

复制构造函数与类的其它函数构造类似,以类名作为函数的名称,第一个参数为该类的常量引用类型。

下面的三种情况要用到复制构造函数:

对象以值传递的方式传入函数参数;

对象以值传递的方式从函数返回;

对象需要通过另外一个对象进行初始化;

编译器有默认的拷贝构造函数,这个函数仅仅是使用老对象的数据成员的值对“新对象”数据成员一一进行赋值,这称为浅拷贝,即只是对象中数据成员进行简单的赋值,这种方式在对象中存在动态成员时则会出现问题,比如对象中的指针。浅拷贝只是使两个指针有相同的值,而不是我们需要的两块不同的地址。

深拷贝,对于对象中动态成员,不仅仅赋值,还重新动态分配空间,从而使得指针指向两块不同的内存,但内存中的值相同。

在编写函数时,尽量按引用方式传递参数,这样可以避免调用复制构造函数,可以极大地提高程序效率。也可以将拷贝函数放在private中,从而防止默认拷贝的发生。

4、静态类成员

普通类成员只能通过实例化对象访问,静态类成员还可以通过类名直接访问,访问时用::域访问符。在定义静态数据成员时,要在类体外部对静态数据成员初始化。静态数据成员是被所有类对象共享的。

静态数据成员可以是当前的类型,而其他数据成员只能是当前类的指针或引用类型,如:

image.png

针对静态数据成员有如下几点:

静态数据成员可以作为成员函数的默认参数,但是普通成员不可以;

类的静态成员函数只能访问类的静态成员,不能访问普通数据成员;

静态成员函数末尾不能用const关键字修饰;

静态数据成员和静态成员函数在类体之外初始化或定义时,去掉static关键字;

5、运算符重载

运算符重载要用到operator关键字,它其实是函数重载的一种,因为运算符本来就是一个函数。对于重载的运算符,两个函数不能交换顺序,重载是什么顺序,只能用这各顺序调用。

对于++和--运算符,由于涉及前置和后置,故默认情况下,重载运算符没有参数,表示是前置运算;若用整型int作为参数,则表示后置运算。

并不是所有的运算符都可以重载,大多数是可以重载的,但是::,?,:,. 是不能重载的。

6、有关类的sizeof问题

空类也会被实例化,编译器会给类隐含添加一个字节,故空类的sizeof()结果为1;sizeof()用来计算字符串的长度时包含”\0”,strlen()统计的长度不包含”\0”。

构造函数、析构函数都不归入sizeof()统计范围之内。

虚函数由于要维护在虚函数表中的位置,故要占据一个指针的大小。

静态成员也不归入sizeof()统计范围。

总起来说,类的大小与非静态成员大小和虚函数有关,与其他普通成员函数无关。类的大小也遵守内存分配时的字节对齐规则:

image.png

7、友元类与友元方法

当用户希望另一个类可以访问当前类的私有成员时,可以在当前类中将另一个类作为自己的友元类。友元即朋友,私有成员只有朋友可以访问。

若只想让某个成员函数访问类的私有成员,则可以将此函数声明为类的友元函数,即在函数返回值前加上friend关键字。友元函数不仅可以是类成员函数,也可以是全局变量函数。

8、引用和指针的区别

引用是一个变量的别名,引用被创建的同时必须被初始化,指针可以在任何时候被初始化;

不能有NULL引用,引用必须与合法的存储单元关联,指针则可以是NULL;

引用一旦被初始化,就不能改变引用关系,指针则可以随时改变所指的对象。

9、类的继承

继承是面向对象的主要特征之一,它使一个类可以从现有类中派生,而不必重新定义一个新类,类继承时使用“:”运算符。

类继承与访问关系如下表:

image.png

用public继承时,原类中public和protected在派生类中类型不变;

用protected继承时,原类中public和protected在派生类中都变成protected类型;

用private继承时,原类中public和protected在派生类中都变为private类型;

用户在父类派生子类时,可能存在一种情况,即在子类中定义了一个与父类同名的方法,此时称子类隐藏父类方法,这样父类中所有的同名方法包括重载方法均被隐藏。若要访问父类中的方法,可用域访问的方式。

在派生完一个子类后,可以定义一个父类指针,通过子类构造函数为其创建对象。因为编译器对同名方法是静态绑定的,即根据对象定义的类型来确定调用哪个类方法。

在定义方法时,在方法的前面使用virtual关键字,这种是虚方法,使用虚方法可以实现动态绑定,即根据对象运行的类型来确定调用哪个类的方法。在父类中定义的虚方法,在子类中同名的方法,即使前面没有virtual关键字,也为虚方法。

纯虚方法:

C++中除了能定义虚方法外,还可定义纯虚方法,也即抽象方法。一个包含纯虚方法的类称为抽象类。抽象类不能实例化,不能当返回值,不能做函数参数,但可以设置指针,它常用于接口的实现。

抽象类常作为其它类的父类,从抽象类派生的子类要实现父类中所有的纯虚方法。定义纯虚函数的意义在于告诉子类,这个接口是一定要继承的,并且要重写函数体,增强它的功能。

10、子类对象的创建和释放

当从父类派生一个子类,定义一个子类对象时,它将依次调用父类构造函数、子类构造函数,在释放对象时,先调用子类析构函数,再调用父类析构函数;

当定义一个父类对象,调用子类创建一个对象时,它依次调用父类构造函数、子类构造函数,在释放时分两种情况:

1.析构函数不是虚函数,则只调用父类析构函数;

2.析构函数是虚函数(父类),则先调用子类的析构函数,再调用父类析构函数。

由此可见,若父类不是虚析构函数,

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇CSV文件简介及C++实现实例讲解 下一篇c++单行字符串的求和(代码教程)

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目