面试:C++不可继承类

  面试中可能遇到让设计一个无法被继承的类。最简单的实现是将该类的构造函数设置为私有的,然后通过静态成员函数调用私有构造函数实例化对象,这样的类确实不可继承,但是使用起来非常不方便,必须使用静态成员实例化对象,而且对象存储在堆中,无法像一个普通的类一样的被使用。最佳的设计是结合私有构造函、友元、虚拟继承实现。

一、简单实现

 1 class Simple{
 2 private:
 3     Simple(){};
 4     ~Simple(){}
 5 private:
 6     static Simple* getInstance(){
 7         return new Simple();
 8     }
 9     static void deleteInstance(Simple* instance){
10         delete instance;
11     }
12 };

二、最佳实现

 1 template<typename T>
 2 class NoneInherit {
 3     friend T;
 4 private:
 5     NoneInherit() {
 6     }
 7     ~NoneInherit() {
 8     }
 9 };
10
11 class Finalclass: virtual public NoneInherit<Finalclass> {
12 public:
13     Finalclass() {
14     }
15     ~Finalclass() {
16     }
17 };
18
19 //class TestClass: public Finalclass {
20 //};

关键点:

  1. 模板类NoneInherit类,构造函数和析构函数都设置为私有,模板参数T设置为友元,这样友元类可以调用构造函数。例如FinalClass是NoneInherit的友元类,可以使用基类的私有构造函数和析构函数
  2. 虚拟继承virtual是最关键的点。如果继承时去掉virtual,FinalClass还是可以被继承的,那么为什么需要使用虚拟继承呢?因为在普通继承中,每个类只是初始化自己的直接的基类。那意味着,如果不使用virtual,TestClass继承Finalclass,由FinalClass再去调用NoneInherit类,由于FinalClass是NoneInHerit的基类,因此整个继承没有任何问题。由于FinalClass使用了虚拟继承,在创建TestClass的时候,TestClass类的构造函数要负责虚基类NoneInherit类的构造,而NoneInherit的构造函数是私有的,友元关系也无法继承,因此TestClass类没有访问的权限。
时间: 2024-10-15 13:02:04

面试:C++不可继承类的相关文章

继承类中static数据值

1 class A{ 2 static int num = 1; 3 public static void Display(){ 4 System.out.println( num ); 5 } 6 } 7 8 class B extends A{ 9 static int num = 2; 10 public static void Display(){ 11 System.out.println( num ); 12 } 13 } 14 15 class C extends A{ 16 st

虚函数列表: 取出方法 // 虚函数工作原理和(虚)继承类的内存占用大小计算 32位机器上 sizeof(void *) // 4byte

#include <iostream> using namespace std; class A { public: A(){} virtual void geta(){ cout << "A:A" <<endl; } virtual void getb(){ cout << "A:B" <<endl; } }; class B :public A{ public: B(){} virtual void g

Asp.net MVC中三大描述对象之ActionDescriptor 以及继承类ReflectedControllerDescriptor

ActionDescriptor抽象类中几个基本的属性: ControllerName:被描述的Controller名称,去除后缀Controller的名称.例如:HomeController则为Home. ControllerType:属性类型为Type,很好理解为被描述Controller的类型. UniqueId:该属性是用来唯一标识当前描述的Controller的.在其唯有的保护的构造函数中赋值,则说明每一个描述每一个Controller都有唯一的UniqueId.UniqueId的 获

QEvent整理归纳:140种类型,29个继承类,7个函数,3种事件来源

140种事件类型: QEvent::None QEvent::AccessibilityDescription QEvent::AccessibilityHelp QEvent::AccessibilityPrepare QEvent::ActionAdded QEvent::ActionChanged QEvent::ActionRemoved QEvent::ActivationChange QEvent::ApplicationActivate QEvent::ApplicationAct

c#学习4,继承类

using System;using System.Collections.Generic;using System.Linq;using System.Text; namespace 继承{class Program { static void Main(string[] args) { chinese p1=new chinese(); p1.name="陈一姐";p1.sayhello(); p1.户口="fujian"; p1.gongfu(); perso

宏函数定义继承类

//: ORDER.CPP -- Order of constructor calls // with inheritance #include <iostream.h> #define inherit(derived, base) class derived : public base { public: derived() { cout << #derived << endl; } }; class X {}; inherit(A, X) inherit(B, A)

【足迹C++primer】54、继承类的范围,构造函数和拷贝控制

继承类的范围,构造函数和拷贝控制 当用派生类执行函数的时候,首先会在当前的类里面找 如果找不到就一级一级地往上找. Name Lookup Happens at Compile Time class Quote { public: Quote()=default; Quote(const string &book, double sales_price):bookNo(book), price(sales_price) {cout<<"Quote gouzhao functi

【整理】C++虚函数及其继承、虚继承类大小

参考文章: http://blog.chinaunix.net/uid-25132162-id-1564955.html http://blog.csdn.net/haoel/article/details/1948051/ 一.虚函数与继承 1.空类,空类单继承,空类多继承的sizeof #include <iostream> using namespace std; class Base1 { }; class Base2 { }; class Derived1:public Base1

【C/C++学院】0822-类型转换函数与构造转换函数/类的继承/类的继承以及区别/继承静态成员与静态函数//继承实现代码重用/单继承QT案例/多继承简介以及实战/Gpu编程

类型转换函数与构造转换函数 #include<iostream> class fushu { public: explicit fushu(int num)//避免隐式转换,引发歧义 { x = num; y = num; } void print() { std::cout << x << "+" << y << "i" << std::endl; } operator int(); //不支

Java面试准备之String类专项突破+源码分析

String的源码中有很多Arrays的方法使用,建议先参阅Arrays的类库 基本介绍: String是一个比较特殊的类,有很多种建立的方法. 如果使用传统的构造方法比如 String s = new String("字符串");这时的对象会在堆上分配,这时候比较两个字符串地址就不相等,而用""双引号包起来的内容会在常量池中做停留,这时如果有两个内容一样的地址就一样了. 因此,使用==来比较字符串是不靠谱的. String类还实现了三个接口:Serializabl