1. #include <iostream>
  2. #include<string>
  3. #include<map>
  4. #include<vector>
  5. #include"thread_pool.h"
  6.  
  7. using namespace std;
  8. template<class T>
  9. class base{
  10. friend T;/// friend class
  11. private:
  12. base(){}
  13. ~base(){}
  14. };
  15.  
  16. class derived : public virtual base<derived>
  17. {
  18. public:
  19. derived(){}
  20. void show(){
  21. cout<<"can be instanced,but can not be inherited"<<endl;
  22. }
  23. ~derived(){}
  24. };
  25.  
  26. class dderived : public derived{
  27. public:
  28. dderived(){}
  29. ~dderived(){}
  30. };
  31.  
  32. int main()
  33. {
  34. cout << "Hello world!" << endl;
  35. derived d;
  36. d.show();
  37. return ;
  38. }

只要把类A的构造函数和析构函数定义为private类型,那么就不能在类A外部建立类的对象,也不能将类A作为基类进行继承。
因为如果继承,建立对象的时候调用基类的构造函数,因为是private的,所以派生类调用基类构造函数的时候,将会链接失败--》不能继承,但是我们也就不能在类外定义对象了。

-------------

class base{
    friend T;/// friend class
private:
    base(){}
    ~base(){}
};

class derived : public virtual base<derived>
{
public:
    derived(){}
    void show(){
        cout<<"can be instanced,but can not be inherited"<<endl;
    }
    ~derived(){}
};

我们可以看到drived类虚继承(!!!这个 virtual 不能不能不能去掉)自base类,在模板展开的时候derived类被声明为base类的友类,因此可以访问base中的private的部分。

所以可以调用base中被定义为private的构造和析构,定义derived类型的对象是没有任何问题的。

----

class dderived : public derived{}

dderived 是不能被实例化的。why???    <此处应该由  深入探究c++对象模型 这本书>的。

c++对象模型中,构造顺序是,虚拟基类---基类---虚拟指针---初始化列表中的---构造函数 内部的语句

在我们的例子中,就是虚拟基类(base)---基类(derived)---虚拟指针---初始化列表中的---构造函数(dderived(){}),

所以我们就可以知道先会dderived调用虚拟基类base的构造函数,但是对于dderived来说,base的构造函数是不能访问的,因为base的构造函数被定义为private,

并且ddrived不是base的友员类,所以在用dderive构造对象的时候,链接错误,也就是说明drived是不能够被继承的。

下面显示的链接错误《这里应该有  深入理解c++对象模型》

  1. ||=== Build: Debug in rpc (compiler: GNU GCC Compiler) ===|
  2. /home/lizhen/codeblocks/rpc/main.cpp||In constructor dderived::dderived()’:|
  3. /home/lizhen/codeblocks/rpc/main.cpp||error: base<T>::base() [with T = derived]’ is private|
  4. /home/lizhen/codeblocks/rpc/main.cpp||error: within this context|
  5. /home/lizhen/codeblocks/rpc/main.cpp||error: base<T>::~base() [with T = derived]’ is private|
  6. /home/lizhen/codeblocks/rpc/main.cpp||error: within this context|
  7. /home/lizhen/codeblocks/rpc/main.cpp||In destructor dderived::~dderived()’:|
  8. /home/lizhen/codeblocks/rpc/main.cpp||error: base<T>::~base() [with T = derived]’ is private|
  9. /home/lizhen/codeblocks/rpc/main.cpp||error: within this context|
  10. ||=== Build failed: error(s), warning(s) ( minute(s), second(s)) ===|

============================

但是如果derived不是virtual inherit自base类的话,就不会发生链接错误。

如何利用c++编写不能被继承、但可以在类外定义对象的类的更多相关文章

  1. [翻译] 编写高性能 .NET 代码--第五章 通用编码与对象设计 -- 类 vs 结构体

    本章介绍了本书其它部分未涉及到的一些编码和设计原则.包含了一些.NET的应用场景,有些不会造成太大危害,有些则会造成明显的问题.剩下的则根据你的使用方法会产生不同的效果.如果要对本章节出现的原则做一个 ...

  2. 如何利用mixin编写media query的代码

    mixins允许文档作者定义的属性对时可以在其他规则集中重用的模式. Media Queries直译就是“媒体查询”.media就是来指定特定的媒体类型,如屏幕(screen),或者“TV”等,其中“ ...

  3. 用c++编写一个不能被继承的类(但是可以在类外部定义该类的对象)

    据我们知道,我们只要把类的构造函数和析构函数定义为private类型,那么就不能够在外部建立给类的对象,也就不能以给类为基类进行继承,因为如果继承,建立对象的时候将要调用基类的构造函数,但是因为为pr ...

  4. LoadRunner利用ODBC编写MySql脚本

    最近做了几周的LoadRunner测试,有一些心得,记录下来,以便以后查找. LoadRunner测试数据库是模拟客户端去连接数据库服务器,因此,需要协议(或者说驱动的支持).LoadRunner本身 ...

  5. 利用反射编写私有 Private 方法的单元测试

    利用反射编写私有 Private 方法的单元测试 最近在添加一个新feature时,鉴于要给自己的代码一是增加代码的强壮性,二是增加代码测试的覆盖率.但是遇到了有些方法是 Private 的,但是在调 ...

  6. 利用java编写的盲注脚本

    之前在网上见到一个盲注的题目,正好闲来无事,便用java写了个盲注脚本,并记录下过程中的坑 题目源码: <?php header("Content-Type: text/html;ch ...

  7. 品味性能之道<九>:利用Loadrunner编写socket性能测试脚本简述

            一.概述         Loadrunner拥有极为丰富的工具箱,供予我们制造出各种奇妙魔法的能力.其中就有此次要讨论的socket套接字操作.     二.socket概述     ...

  8. Python 利用Python编写简单网络爬虫实例3

    利用Python编写简单网络爬虫实例3 by:授客 QQ:1033553122 实验环境 python版本:3.3.5(2.7下报错 实验目的 获取目标网站“http://bbs.51testing. ...

  9. Python 利用Python编写简单网络爬虫实例2

    利用Python编写简单网络爬虫实例2 by:授客 QQ:1033553122 实验环境 python版本:3.3.5(2.7下报错 实验目的 获取目标网站“http://www.51testing. ...

随机推荐

  1. codeblocks winsock配置

    在codeblocks进行Socket编程遇到如下情况: undefined reference to WSAStartup@8 解决方法: 右击工程,选择 build options,选择 Link ...

  2. Coursera 算法二 week 3 Baseball Elimination

    这周的作业不需要自己写算法,只需要调用库函数就行,但是有些难以理解,因此用了不少时间. import edu.princeton.cs.algs4.FlowEdge; import edu.princ ...

  3. SQL Server Profiler查询跟踪的简单使用

    1.打开SQL Server Management Studio,选择工具->SQL Server Profiler,或者直接从路径:开始/程序/Microsoft SQL Server 200 ...

  4. 编写WsHttpBinding的WCF通信方式

    这个通信方式本人实验了好久,需要一个重要的条件是服务端和客户端的发送内容方式都是相同的声明,需要在配置文件写入,客户端: <system.serviceModel> <binding ...

  5. fdisk - Linux分区表操作工具软件

    总览 fdisk [-u]设备名 fdisk -l [-u] [设备名 ...] fdisk -s分区 ... fdisk -v 描述 硬盘可以被分成一个或多个逻辑磁盘,称为 分区. 这些分区信息都存 ...

  6. python_32_文件操作1

    #目录里先创建一个yesterday文件 '''对文件操作流程: 打开文件,得到文件句柄并赋值给一个变量 通过句柄对文件进行操作 关闭文件 ''' print(open('yesterday',enc ...

  7. 阿里云服务器下安装LAMP环境(CentOS Linux 6.3) 安装与配置 FTP 服务器

    我们经常会使用 FTP,把本地电脑上的文件上传到服务器上,或者把服务器上的文件下载到自己的电脑里面.FTP 有服务端和客户端,FTP 的服务端提供了这种传输文件的服务,FTP 的客户端提供了传输文件的 ...

  8. 按格式读取csv文件内容

    string path = @"C:\Users\keen_\Downloads\upload\upload\Upload\20140701141934_export.csv"; ...

  9. css与html结合四种方式

    方式一:每个标签加一个属性法 <div style="background-color:red;color:green;"></div> 方式二:head中 ...

  10. HTML5中最看重的理念“语义化”相比HTML有什么区别?

    这里搜集整理了一些语义化标签方面的问题和解答,以供大家参考. 语义化这个概念应该说是伴着HTML5应运而生,那么什么是HTML5中所谓的语义化? 简单来说就是:描述内容的含义(meaning) 比如说 ...