您的位置:首页 > 职场人生

面向对象相关面试题归总

2016-11-09 18:20 253 查看
面试中遇到几个面向对象相关的基础问题,记录以供后续学习。

 

问题1、设计一个不能被继承的类。

一个类不能被继承,也就是说它的子类不能构造父类,这样子类就没有办法实例化整个子类从而实现子类无法继承父类。我们可以将一个类的构造函数声明为私有,使得这个类的构造函数对子类不可见,那么这个类也就不能继承了。但是,这引出一个问题,客户程序岂不是也无法实例化这个类了?参考一下Singleton模式,用一个static函数来帮助创建这个类的实例,问题就解决了,但是还是不能像一般类那样实例化。

换个思路考虑一下,友元不也是不能被继承的么?现在设想一下,有一个CParent类,我们不希望他能够被继承。在友元不能被继承的思路指引下,我们要考虑让CParent的友元属性不能被继承。假设有一个辅助类CNoHeritance,CParent是CNoHeritance类的友元。还要假设一个CChild类,它试图去继承CParent类(如果它有这个能耐的话)。

先把CNoHeritance类的构造函数定义成private,然后将CParent声明为CNoHeritance的友元类。同时CParent继承了CNoHeritance类。到目前为止,CNoHeritance除了CParent类以外,谁也无法对它进行访问和实例化。CChild因为无法继承CParent的友元特性,所以CChild无法对CNoHeritance直接进行实例化(但是可以通过CParent)。

如果我们让CParent类虚继承CNoHeritance类,根据虚继承的特性,虚基类的构造函数由最终的子类负责构造。因此CChild如果要想继承CParent,它必须能够构造CNoHeritance,这是不可能的!因此,我们的CParent也就终于成为了一个无法继承的类。

class CNoHeritance
{
private:
CNoHeritance(){}
~CNoHeritance(){}
friend class CParent;
};

class CParent : virtual public CNoHeritance
{
public:
CParent(int v){m_v = v;}
~CParent(){};
private:
int m_v;

public:
void fun(){cout << "The value is: " << m_v << endl;}
};

class CChild : public CParent
{
public:
CChild():CParent(10){}
~CChild(){}
};


问题2、简述多态的实现机制。

C++多态是基于虚表实现的。编译器会为含有虚函数的类创建一个虚函数表,用于保存虚函数入口地址。当有继承关系时,虚表也被继承,如果有虚函数被重写,则虚表中函数地址也会被替换。当实例化一个对象时,对象中有一个指向所属类虚表的指针。通过该指针就可以调用到正确的函数。

 

问题3、什么情况下会触发多态?对象、引用还是指针?

(1)      虚函数

(2)      父类指针或引用指向子类对象。对象本身默认不会多态。

 

问题4、虚继承解决什么问题?

为了解决从不同途径继承来的同名的数据成员在内存中有不同的拷贝造成数据不一致问题,将共同基类设置为虚基类。这时从不同的路径继承过来的同名数据成员在内存中就只有一个拷贝,同一个函数名也只有一个映射。这样不仅就解决了二义性问题,也节省了内存,避免了数据不一致的问题。

构造函数执行顺序:

首先执行虚基类的构造函数,多个虚基类的构造函数按照被继承的顺序构造;

执行基类的构造函数,多个基类的构造函数按照被继承的顺序构造;

执行成员对象的构造函数,多个成员对象的构造函数按照申明的顺序构造;

执行派生类自己的构造函数;

析构以与构造相反的顺序执行;

从虚基类直接或间接派生的派生类中的构造函数的成员初始化列表中都要列出对虚基类构造函数的调用。但只有用于建立对象的最派生类的构造函数调用虚基类的构造函数,而该派生类的所有基类中列出的对虚基类的构造函数的调用在执行中被忽略,从而保证对虚基类子对象只初始化一次。

在一个成员初始化列表中同时出现对虚基类和非虚基类构造函数的调用时,虚基类的构造函数先于非虚基类的构造函数执行。

 

问题5、虚函数、虚析构函数应用在什么场景?

用来做基类的类的析构函数一般都是虚函数。这样做是为了当用一个基类的指针删除一个派生类的对象时,派生类的析构函数会被调用,否则派生类析构函数不会被调用,造成内存泄漏。

当然,并不是要把所有类的析构函数都写成虚函数。因为当类里面有虚函数的时候,编译器会给类添加一个虚函数表,里面来存放虚函数指针,这样就会增加类的存储空间。所以,只有当一个类被用来作为基类的时候,才把析构函数写成虚函数。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: