C++总结(2)

C++总结(2)
1.面向对象:将数据与函数绑定到一起,进行封装,减少了重复代码的重写过程.
封装:类,将数据与操作数据的方法封装成类,仅留对外公开接口和对象来进行交互。
继承:在使用现有类的继承上,对该类的功能进行扩展
public: protected: privated:
多态:用父类类别的指针来指向子类的实例,通过父类指针调用实际子类的成员函数。(两种实现方法
重写:子类中的新方法将覆盖父类中原有的方法。
重载:静态多态 函数或者方法有同样的名称,但参数列表不相同
C语言实现C++的重载需要使用函数指针来实现,重载的函数不是同名称,且只是类似的实现了函数重载功能

2,构造函数有几种,作用
默认构造函数、初始化构造函数、拷贝构造函数、移动构造函数。
默认构造函数和初始化构造函数,在定义类的对象的时候,完成对象的初始化工作。有了有参构造(初始化构造函数),编译器就不提供默认的构造函数。
拷贝构造函数、移动构造函数
拷贝构造函数是浅拷贝(复制了对象的引用地址,两个对象指向同一个内存地址,所以修改其中任意的值,另一个值都会随之变化,这就是浅拷贝)。
深拷贝:将对象及值复制过来,两个对象修改其中任意的值另一个值不会改变,这就是深拷贝。(包含了new初始化的指针成员时,应当定义一个深拷贝构造函数,来复制指向的数据,而不是指针)
深拷贝的实现:深拷贝的拷贝构造函数和赋值运算符的重载传统实现:

移动构造函数。用于将其他类型的变量,隐式转换为本类对象。下面的转换构造函数,将int类型的r转换为Student类型的对象,对象的age为r,num为1004。 Student(int r) { int num=1004; int age= r; }

只定义析构函数,会自动生成哪些构造函数(拷贝构造函数和默认构造函数)

3.一个类,默认会生成哪些函数
无参构造函数
拷贝构造函数
赋值运算符
析构函数(非虚)

4.C++ 类对象的初始化顺序,有多重继承情况下的顺序
构造:父类构造函数–>成员类对象构造函数–>自身构造函数
成员变量的初始化与声明顺序有关,构造函数的调用顺序是类派生列表中的顺序。
析构顺序和构造顺序相反。

5.下向上转换和上向下转型(类型转换)
子类转换为父类:向上转型,使用dynamic_cast<type_id>(expression),这种转换相对来说比较安全不会有数据的丢失;

父类转换为子类:向下转型,可以使用强制转换(4种方法皆可,一般可使用static_cast ),这种转换时不安全的,会导致数据的丢失,原因是父类的指针或者引用的内存中可能不包含子类的成员的内存。

6.简述一下 C++ 中的多态
派生类重写基类方法,然后用基类引用指向派生类对象,调用方法时候会进行动态绑定,这就是多态。 多态分为静态多态和动态多态:
1.静态多态:编译器在编译期间完成的,编译器会根据实参类型来推断该调用哪个函数,如果有对应的函数,就调用,没有则在编译时报错。

2.其实要实现动态多态,需要几个条件—即动态绑定条件:
虚函数。基类中必须有虚函数,在派生类中必须重写虚函数。
通过基类类型的指针或引用来调用虚函数。

7.为什么要虚析构,为什么不能虚构造
虚析构:将可能会被继承的父类的析构函数设置为虚函数,可以保证当我们new一个子类,然后使父类指针指向该子类对象,释放基类指针时可以释放掉子类的空间,防止内存泄漏。如果基类的析构函数不是虚函数,在特定情况下会导致派生来无法被析构。

8.模板类是在什么时候实现
模板实例化:模板的实例化分为显示实例化和隐式实例化,前者是研发人员明确的告诉模板应该使用什么样的类型去生成具体的类或函数,后者是在编译的过程中由编译器来决定使用什么类型来实例化一个模板不管是显示实例化或隐式实例化,最终生成的类或函数完全是按照模板的定义来实现的。

模板具体化:当模板使用某种类型类型实例化后生成的类或函数不能满足需要时,可以考虑对模板进行具体化。

9.移动构造函数
C++11中新增了移动构造函数。与拷贝类似,移动也使用一个对象的值设置另一个对象的值。但是,又与拷贝不同的是,移动实现的是对象值真实的转移(源对象到目的对象):源对象将丢失其内容,其内容将被目的对象占有

10. C++ 类内可以定义引用成员变量?
不能用默认构造函数初始化,必须提供构造函数来初始化引用成员变量。否则会造成引用未初始化错误。
构造函数的形参也必须是引用类型。
不能在构造函数里初始化,必须在初始化列表中进行初始化。

11.简述一下什么是常函数,有什么作用
类的成员函数后面加 const,表明这个函数不会对这个类对象的数据成员(准确地说是非静态数据成员)作任何改变

12.说说什么是虚继承,解决什么问题,如何实现?
虚继承是解决C++多重继承问题的一种手段,从不同途径继承来的同一基类,会在子类中存在多份拷贝。这将存在两个问题:其一,浪费存储空间;第二,存在二义性问题,通常可以将派生类对象的地址赋值给基类对象,实现的具体方式是,将基类指针指向继承类中的基类对象的地址,但是多重继承可能存在一个基类的多份拷贝,这就出现了二义性。虚继承可以解决多种继承前面提到的两个问题

13.简述一下虚函数和纯虚函数,以及实现原理
C++中的虚函数的作用主要是实现了多态的机制。关于多态,简而言之就是用父类型的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数
虚函数(Virtual Function)是通过一张虚函数表(Virtual Table)来实现的。简称为V-Table。在这个表中,主是要一个类的虚函数的地址表,这张表解决了继承、覆盖的问题,保证其容真实反应实际的函数。这样,在有虚函数的类的实例中这个表被分配在了这个实例的内存中,所以,当我们用父类的指针来操作一个子类的时候,这张虚函数表就显得由为重要了,它就像一个地图一样,指明了实际所应该调用的函数。
纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。在基类中实现纯虚函数的方法是在函数原型后加“=0” virtualvoid GetName() =0。在很多情况下,基类本身生成对象是不合情理的。例如,动物作为一个基类可以派生出老虎、孔雀等子类,但动物本身生成对象明显不合常理。为了解决上述问题,将函数定义为纯虚函数,则编译器要求在派生类中必须予以重写以实现多态性。同时含有纯虚函数的类称为抽象类,它不能生成对象。这样就很好地解决了上述两个问题。将函数定义为纯虚函数能够说明,该函数为后代类型提供了可以覆盖的接口,但是这个类中的函数绝不会调用。声明了纯虚函数的类是一个抽象类。所以,用户不能创建类的实例,只能创建它的派生类的实例。必须在继承类中重新声明函数(不要后面的=0)否则该派生类也不能实例化,而且它们在抽象类中往往没有定义。定义纯虚函数的目的在于,使派生类仅仅只是继承函数的接口。纯虚函数的意义,让所有的类对象(主要是派生类对象)都可以执行纯虚函数的动作,但类无法为纯虚函数提供一个合理的缺省实现。所以类纯虚函数的声明就是在告诉子类的设计者,“你必须提供一个纯虚函数的实现,但我不知道你会怎样实现它”。

纯虚函数不可以实例化,但是可以用其派生类实例化
纯虚函数的类被称为抽象类,而只含有虚函数的类不能被称为抽象类
纯虚函数必须在子类中实现该函数才可以使用,因为纯虚函数在基类有声明而没有定义。

14.菱形继承给出一个菱形继承问题的解决方案。如果Lion类和Tiger类在分别继承Animal类时都用virtual来标注,对于每一个Liger对象,C++会保证只有一个Animal类的子对象会被创建

15.构造函数中的能不能调用虚方法
从语法上讲,调用完全没有问题,但是从效果上看,往往不能达到需要的目的。派生类对象构造期间进入基类的构造函数时,对象类型变成了基类类型,而不是派生类类型。同样,进入基类析构函数时,对象也是基类类型。

16.拷贝构造函数的参数是什么传递方式,为什么
拷贝构造函数的参数必须使用引用传递,传值的方式会调用该类的拷贝构造函数,从而造成无穷递归地调用拷贝构造函数。( 传指针也是传值)

17.抽象类有如下几个特点:
(1)抽象类只能用作其他类的基类,不能建立抽象类对象。
(2)抽象类不能用作参数类型、函数返回类型或显式转换的类型。
(3)可以定义指向抽象类的指针和引用,此指针可以指向它的派生类,进而实现多态性。

18 什么是多态?除了虚函数,还有什么方式能实现多态?
多态是面向对象的重要特性之一,它是一种行为的封装,就是不同对象对同一行为会有不同的状态。(学生和成人都去买票时,学生会打折,成人不会)
多态是以封装和继承为基础的。在C++中多态分为静态多态(早绑定)和动态多态(晚绑定)两种,其中动态多态是通过虚函数实现,静态多态通过函数重载实现,代码如下:

19什么是虚基类,可否被实例化?
被继承的类前面加上virtual关键字,这时被继承的类称为虚基类。虚继承的类可以被实例化

20.简述一下拷贝赋值和移动赋值?
拷贝赋值是通过拷贝构造函数来赋值,在创建对象时,使用同一类中之前创建的对象来初始化新创建的对象。
移动赋值是通过移动构造函数来赋值,二者的主要区别在于
1)拷贝构造函数的形参是一个左值引用,而移动构造函数的形参是一个右值引用;
2)拷贝构造函数完成的是整个对象或变量的拷贝,而移动构造函数是生成一个指针指向源对象或变量的地址,接管源对象的内存,相对于大量数据的拷贝节省时间和内存空间。

21.虚函数表里存放的内容是什么时候写进去的?
虚函数表是一个存储虚函数地址的数组,以NULL结尾。虚表(vftable)在编译阶段生成,对象内存空间开辟以后,写入对象中的 vfptr,然后调用构造函数。即:虚表在构造函数之前写入
每个类都有自己的虚表,除了在构造函数之前写入之外,我们还需要考虑到虚表的二次写入机制,通过此机制让每个对象的虚表指针都能准确的指向到自己类的虚表,为实现动多态提供支持。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值