【题目 16】拷贝构造函数的格式和作用,自动调用拷贝构造函数的几种情形?
格式:没有返回值 函数名和类名相同 参数:const person& 类型引用
作用:逐个给成员变量进行赋值三种情形下会调用拷贝构造函数
(1) 当用一个已有对象给另一个同类的对象进行初始化时 person a = b;
(2) 当一个函数的参数是一个类的对象时 void fun(person p); fun(a);
(3) 当一个函数的返回值是一个类的对象时 person fun(); person a = fun();
问题: 拷贝构造函数是值传递还是什么,为什么?
引用传递
因为使用值传递导致无限拷贝,进入死循环
person(const person other)//const person other = a;拷贝
{ }
person a;
person b = a;
【题目 17】深拷贝与浅拷贝的区别?
当类中有指针成员时,
1.浅拷贝只将指针中保存的地址复制给新的对象,实际上还是指的同一块内存,当析构函数对两个对象进行内 存释放时会出现 double free 异常(释放第一个对象时,已将内存删除,第二个对象释放时还是找的原有地址, 但内存已不存在)。
2.深拷贝拷贝时不拷贝地址,是将原对象指针中指向的内存进行拷贝,新对象指针存储新内存的地址,原对象指针存储原内存的地址,所以释放时互不干扰。 (系统默认的拷贝构造:浅拷贝)
【题目 18】友元的作用及特点?
当在类的外面想要使用该类的私有成员,可以通过友元来破坏封装性;
可以使用友元函数(在类外编写函数,在类内声明为友元函数)、友元类(声明一个类来访问另一个类中的私有成员)。
特点:友元不能继承,友元不能传递,友元是单向的。
【题目 19】设计模式--单例模式
作用:单例模式是保证程序中这个类只有一个实例对象;
什么情况下想到使用单例模式:有一个类的功能,多处都要使用,多次的创建与销毁。
实现方式:
1.构造函数和拷贝构造函数私有化,保证在类的外部不能创建和拷贝对象(0 例)
2.在类的内部留出一个静态私有的本类的指针用来承接惟一的实例,并在类外初始为 NULL
3.在类的内部编写一个静态公有函数来获取实例,判断指针是否存有地址。
如果有地址,则直接返回实例,如果没有,使用 new 关键字创建一个实例并返回。
class One
{
One(){}
One(const One& other){}
static One* instance;
public:
static One* getInstance()
{
if(instance == NULL)
instacne = new One;
return instance;
}
};
One* One::instacne = NULL;
int main()
{
One* p = One::getInstance();
One* p1 = One::getInstance();
//p 和 p1 地址是相同的
}
【题目 20】C++异常处理有几个步骤
步骤:先 try(检测),遇到异常时 throw(抛出),在检测块外对抛出的异常进行 catch(捕获),并处理。
void fun(int a)
{
if(a == 0)
throw a;
cout<<a<<endl;//不会执行}
int main(){
try
{
//待检测语句
fun(0);
cout<<”----”<<endl;//不执行
}
catch(int a)
{
cout<<a<<endl;//0
}
【题目 21】面向对象的三大特征是什么?请简要描述一下?
(1) 封装,将具有相同属性和行为的一系列对象封装成一个类,将一系列重复性的代码封装成函数,数据的隐藏,将不对外公开的属性和行为使用 private 进行修饰,保证数据安全。
(2) 继承,子类继承父类的变量和函数,C++的继承允许一个子类同时继承多个父类。
(3) 多态,一种状态多种表现形式,具体体现在父类指针(引用)指向子类对象。
【题目 22】类中默认存在的函数有哪些,为类 Empty 写出函数的定义?
默认存在的函数有:
默认的构造 默认的拷贝 默认的析构 =运算符重载 &运算符重载
Empty(){}
Empty(const Empty& o){}
~Empty(){}
Empty& operator= (const Empty& other){}
Empty* operator& (){ }
【题目 23】在继承时,继承方式都有什么影响?
当用 public 继承时,派生类继承到的所有成员访问权限不变。
当用 protected 继承时,派生类继承到的 public 成员变为 protected,其余不变。
当用 private 继承时,派生类继承到的所有成员都为 private。
【题目 24】什么是虚函数?虚函数有什么作用?
使用 virtual 关键字修饰的函数,为虚函数。
作用:实现运行时多态;
当父类指针(引用)指向子类对象时,调用一个父类和子类都有的函数,如果父类的是虚函数,那么调用的是 子类覆盖(重写)后的,如果不是虚函数则调用父类原有的,调用子类重写的。
【题目 25】C++重写(覆盖)、重载、重定义(遮蔽)的区别?
重载特征:
1、相同的范围(在同一个类中/同一个作用域内)
2、函数名字相同
3、参数列表不同
4、virtual 关键字可有可无
重写(覆盖)是指派生类函数覆盖基类函数,特征是:
1、不同的范围,分别位于基类和派生类中
2、函数的名字相同
3、参数相同,返回值相同
4、基类函数必须有 virtual 关键字
重定义(隐藏)是指派生类的函数屏蔽了与其同名的基类函数,规则如下:
1、如果派生类的函数和基类的函数同名,但是参数不同,此时,不管有无 virtual,基类的函数被隐藏。
2、如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有 vitual 关键字,此时, 基类的函数被隐藏。
【题目 26】多态有几种,如何实现的运行时多态?
多态分为:编译时多态,运行时多态 或者 (静态多态、动态多态)
静态多态:函数重载与泛型编程,静态多态是程序调用函数,编译器决定使用哪个可执行代码块。
动态多态:是由继承机制及虚函数实现的。通过父类指针指向子类对象,访问派生类中同名重写成员函数。
多态的作用:同一个事务具有了多种的表现形态;把不同的子类对象都当作父类来看,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,以适应需求的不断变化。
1.实现的方法:子类继承父类,重写父类中的虚函数。父类指针指向子类对象时,可以通过父类的指针调用子类中重写的函数。
2.多态存在的 3 个条件
1)有继承
2)有重写(虚函数)
3)父类指针或引用指向子类对象
【题目 27】什么是纯虚函数,什么是抽象类?
1.纯虚函数格式:直接在虚函数声明时=0;virtual void fun() = 0;
2.纯虚函数在父类中没有具体实现,在具体的实现子类中重写实现。
3.抽象类:至少有一个纯虚函数的类叫抽象类,抽象类不能实例化对象,但是可以声明抽象类的指针; 抽象类时专门被继承的,纯虚函数专门被子类重写的。
4. 抽象类可以被继承,继承的派生类如果不是抽象类,必须要实现纯虚函数
class shape 抽象类
{
virtual void fun1() = 0;virtual void fun2() = 0;
virtual void fun3() = 0;
};
class B: public Shape //子类 B 也变成了抽象类
{
void fun1(){}
//继承了两个纯虚函数
};
【题目 28】虚析构函数的作用
多态时,当用父类指针指向子类对象时,释放父类对象时不会调用子类的析构函数,所以定义父类的析构函数 时需要加 virtual,使其成为虚析构函数;
结语
本次C++面试题分享到此结束,以上有些内容我主页有单独讲解,大家觉得有用的话,可以点点赞,点点关注,后续还会分享有关C++知识,谢谢大家!