From:http://blog.csdn.net/lazy_tiger/article/details/2224899

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

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

    int m_v;
    static CParent * m_instance;
public:
void fun(){cout << "The value is: " << m_v << endl;}
    static CParent * getInstance(int v);
};
CParent * CParent::m_instance = NULL;

CParent * CParent::getInstance(int v)
{
    m_instance = new CParent(v);
    return m_instance;
}

这是一个有效的方法,但是static函数创建出来的实例必然是static的。而且,这个类不能像普通的类那样构建对象,比如:

CParent c;  // impossible

换个思路考虑一下,友元不也是不能被继承的么?我们可以把类的构造函数定义为private的同时,定义友元函数来帮助构造类的实例。

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

    int m_v;
public:
    void fun(){cout << "The value is: " << m_v << endl;}
    friend CParent * getInstance(int v);
};

CParent * getInstance(int v)
{
    CParent * pinstance = new CParent(v);
    return pinstance;
}

这个类也是不能被继承的,但是出现的问题和前面一样:我们还是不能像对普通类那样对待这个类。

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

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

到目前为止,CParent还是可以被继承的。这是一个trick.让我们整理一下思路,下面的图说明了CNoHeritance, CParent和CChild三个类之间的关系。

如果我们让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(){}
};

需要注意的是,我们这里引入的CNoHeritance类对整个程序而言,只引入了Private的构造函数和析构函数,所以不会因为可能的菱形继承带来二义性.

[转]实现一个无法被继承的C++类的更多相关文章

  1. 用C++设计一个不能被继承的类(用私有构造函数+友元函数)

    题目:用C++设计一个不能被继承的类. 分析:这是Adobe公司2007年校园招聘的最新笔试题.这道题除了考察应聘者的C++基本功底外,还能考察反应能力,是一道很好的题目. 在Java中定义了关键字f ...

  2. 探讨C++实现一个不可被继承的类

    C#和Java都提供了一种机制让一个类不能被继承,如C#中的sealed关键字和Java的final关键字,然而C++程序员就没这么好命了.不过C++也可以模拟出这种效果,原理基于:子类的构造函数会自 ...

  3. 用C++设计一个不能被继承的类(转)

    在Java 中定义了关键字final,被final修饰的类不能被继承. 首先想到的是在C++中,子类的构造函数会自动调用父类的构造函数.同样,子类的析构函数也会自动调用父类的析构函数.要想一个类不能被 ...

  4. 3.实现一个名为Person的类和它的子类Employee,Employee有两个子类Faculty 和Staff。

    23.实现一个名为Person的类和它的子类Employee,Employee有两个子类Faculty 和Staff. 具体要求如下: (1)Person类中的属性有:姓名name(String类型) ...

  5. classmethod一个用处是创建可选类构造器

    Definition and Introduction通常来说, descriptor 是一种绑定着特殊行为属性的对象, 在访问它时行为被descriptor协议定义的方法所重载.这些方法是__get ...

  6. 一天一个Java基础——对象和类

    1.在Java中你所做的全部工作就是定义类,产生那些类的对象,以及发送消息给这些对象 2.可以在类中设置两种类型的元素:字段(也被称作数据成员)和方法(也被称作成员函数) 3.字段可以是任何类型的对象 ...

  7. 一个漂亮的php验证码类

    一个漂亮的php验证码类(分享)   作者: 字体:[增加 减小] 类型:转载 下面小编就为大家分享一个漂亮的php验证码类.需要的朋友可以过来参考下   直接上代码: 复制代码 代码如下: //验证 ...

  8. 设计一个 Java 程序,自定义异常类,从命令行(键盘)输入一个字符串,如果该字符串值为“XYZ”。。。

    设计一个 Java 程序,自定义异常类,从命令行(键盘)输入一个字符串,如果该字符串值为“XYZ”,则抛出一个异常信息“This is a XYZ”,如果从命令行输入 ABC,则没有抛出异常.(只有 ...

  9. CSS一个元素同时使用多个类选择器(class selector)

    CSS类选择器参考手册 一个元素同时使用多个类选择器 CSS中类选择器用点号表示.实际项目中一个div元素为了能被多个样式表匹配到(样式复用),通常div的class中由好几段组成,如<div ...

随机推荐

  1. 劈荆斩棘:Gitlab 部署 CI 持续集成

    阅读目录: install configue gitlab-ci-multi-runner restore nuget packages bulid .sln run unit tests confi ...

  2. 如何重新注册VMware Update Manager(VUM)至vCenter Server中

    在VMware的vSphere化境中,VUM的角色相当于Windows 环境中的WSUS(Windows 更新服务器),可以批量,自动化的完成所管辖ESXi主机的大版本迁移,小版本升级的任务,深受管理 ...

  3. 你真的会玩SQL吗?你所不知道的 数据聚合

    你真的会玩SQL吗?系列目录 你真的会玩SQL吗?之逻辑查询处理阶段 你真的会玩SQL吗?和平大使 内连接.外连接 你真的会玩SQL吗?三范式.数据完整性 你真的会玩SQL吗?查询指定节点及其所有父节 ...

  4. ASP.NET Core 中文文档 第三章 原理(14)服务器

    原文:Servers 作者:Steve Smith 翻译:谢炀(Kiler) 校对:许登洋(Seay).姚阿勇(Dr.Yao) ASP.NET Core 已完全从承载应用程序的 Web 服务器环境中分 ...

  5. Apache Hadoop2.x 边安装边入门

    完整PDF版本:<Apache Hadoop2.x边安装边入门> 目录 第一部分:Linux环境安装 第一步.配置Vmware NAT网络 一. Vmware网络模式介绍 二. NAT模式 ...

  6. Kafka消费组(consumer group)

    一直以来都想写一点关于kafka consumer的东西,特别是关于新版consumer的中文资料很少.最近Kafka社区邮件组已经在讨论是否应该正式使用新版本consumer替换老版本,笔者也觉得时 ...

  7. GridView详细介绍

    GridView控件的属性 表10.6 GridView控件的行为属性属性描述AllowPaging指示该控件是否支持分页.AllowSorting指示该控件是否支持排序.AutoGenerateCo ...

  8. C#开发微信门户及应用(10)--在管理系统中同步微信用户分组信息

    在前面几篇文章中,逐步从原有微信的API封装的基础上过渡到微信应用平台管理系统里面,逐步介绍管理系统中的微信数据的界面设计,以及相关的处理操作过程的逻辑和代码,希望从更高一个层次,向大家介绍微信的应用 ...

  9. 成就PHP高手的五个必由之路

    亲们,此文时转载过来的,不是原创!特此说明一下 原文名称:5 ways to be a better php developer原文链接:http://www.developertutorials.c ...

  10. 关闭firefox的plugincheck

    每次打开firefox都弹出这个SB页面: https://www.mozilla.org/en-US/plugincheck/ 关不掉, 很是烦人. 经过地番google,找到了答案: about: ...