返回介绍

第1章 面试的流程

第2章 面试需要的基础知识

第3章 高质量的代码

第4章 解决面试题的思路

第5章 优化时间和空间效率

第6章 面试中的各项能力

第7章 两个面试案例

面试题48:不能被继承的类

发布于 2024-08-21 20:57:09 字数 1830 浏览 0 评论 0 收藏 0

题目:用C++设计一个不能被继承的类。

在C#中定义了关键字sealed,被sealed修饰的类不能被继承。在Java中同样也有关键字final表示一个类型不能被继承。在C++中没有类似于sealed和final的关键字,我们只有自己来实现。

常规的解法:把构造函数设为私有函数

很多人都能够想到,在C++中子类的构造函数会自动调用父类的构造函数,子类的析构函数也会自动调用父类的析构函数。要想一个类不能被继承,我们只要把它的构造函数和析构函数都定义为私有函数。那么当一个类试图从它那继承的时候,必然会由于调用构造函数、析构函数而导致编译错误。

可是这个类型的构造函数和析构函数都是私有函数,我们怎样才能得到该类型的实例呢?我们可以通过定义公有的静态函数来创建和释放类的实例。基于这个思路,我们可以写出如下代码:

这个类是不能被继承,但总觉得它和普通的类型有些不一样,使用起来有点不方便。比如我们只能得到位于堆上的实例,而得不到位于栈上的实例。

新奇的解法:利用虚拟继承,能给面试官留下很好的印象

能不能实现一个与一般的类型相比除了不能被继承之外其他用法都一样的类型呢?办法还是有的,不过需要一定的技巧。请看如下代码:

这个SealedClass2使用起来和一般的类型没有区别,我们可以在栈上、也可以在堆上创建实例。尽管类MakeSealed<SealedClass2>的构造函数和析构函数都是私有的,但由于类SealedClass2是它的友元类型,因此在SealedClass2中调用MakeSealed<SealedClass2>的构造函数和析构函数都不会引起编译错误。

但当我们试图从SealedClass2中继承一个类并创建它的实例的时候,却不能通过编译。比如我们从SealedClass2中继承出类型Try:

由于类SealedClass2是从类MakeSealed<SealedClass2>虚继承过来的,在调用Try的构造函数的时候,会跳过SealedClass2而直接调用MakeSealed<SealedClass2>的构造函数。非常遗憾的是,Try不是MakeSealed<SealedClass2>的友元类型,因此不能调用它的私有构造函数。

通过上面的分析,我们发现从SealedClass2继承的类,一旦实例化就会导致编译出错,因此SealedClass2不能被继承,这也就满足了题目的要求。

注:第二种方法的可移植性不好。虽然SealedClass2在Visual Studio中能够编译,但由于GCC中对friend的要求不同于Visual Studio,目前在最新的GCC中还不支持模板参数类型作为友元类型。

源代码:

本题完整的源代码详见48_SealedClass项目。

本题考点:

- 考查发散思维能力。当要求设计一个不能被继承的类时,应聘者要马上从把构造函数定义为私有函数出发去寻找解题方法。

- 考查对C++多个概念的理解,比如构造函数、模板、友元等。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文