如何利用c++编写不能被继承、但可以在类外定义对象的类
#include <iostream>
#include<string>
#include<map>
#include<vector>
#include"thread_pool.h" using namespace std;
template<class T>
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(){}
}; class dderived : public derived{
public:
dderived(){}
~dderived(){}
}; int main()
{
cout << "Hello world!" << endl;
derived d;
d.show();
return ;
}
只要把类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++对象模型》
||=== Build: Debug in rpc (compiler: GNU GCC Compiler) ===|
/home/lizhen/codeblocks/rpc/main.cpp||In constructor ‘dderived::dderived()’:|
/home/lizhen/codeblocks/rpc/main.cpp||error: ‘base<T>::base() [with T = derived]’ is private|
/home/lizhen/codeblocks/rpc/main.cpp||error: within this context|
/home/lizhen/codeblocks/rpc/main.cpp||error: ‘base<T>::~base() [with T = derived]’ is private|
/home/lizhen/codeblocks/rpc/main.cpp||error: within this context|
/home/lizhen/codeblocks/rpc/main.cpp||In destructor ‘dderived::~dderived()’:|
/home/lizhen/codeblocks/rpc/main.cpp||error: ‘base<T>::~base() [with T = derived]’ is private|
/home/lizhen/codeblocks/rpc/main.cpp||error: within this context|
||=== Build failed: error(s), warning(s) ( minute(s), second(s)) ===|
============================
但是如果derived不是virtual inherit自base类的话,就不会发生链接错误。
如何利用c++编写不能被继承、但可以在类外定义对象的类的更多相关文章
- [翻译] 编写高性能 .NET 代码--第五章 通用编码与对象设计 -- 类 vs 结构体
本章介绍了本书其它部分未涉及到的一些编码和设计原则.包含了一些.NET的应用场景,有些不会造成太大危害,有些则会造成明显的问题.剩下的则根据你的使用方法会产生不同的效果.如果要对本章节出现的原则做一个 ...
- 如何利用mixin编写media query的代码
mixins允许文档作者定义的属性对时可以在其他规则集中重用的模式. Media Queries直译就是“媒体查询”.media就是来指定特定的媒体类型,如屏幕(screen),或者“TV”等,其中“ ...
- 用c++编写一个不能被继承的类(但是可以在类外部定义该类的对象)
据我们知道,我们只要把类的构造函数和析构函数定义为private类型,那么就不能够在外部建立给类的对象,也就不能以给类为基类进行继承,因为如果继承,建立对象的时候将要调用基类的构造函数,但是因为为pr ...
- LoadRunner利用ODBC编写MySql脚本
最近做了几周的LoadRunner测试,有一些心得,记录下来,以便以后查找. LoadRunner测试数据库是模拟客户端去连接数据库服务器,因此,需要协议(或者说驱动的支持).LoadRunner本身 ...
- 利用反射编写私有 Private 方法的单元测试
利用反射编写私有 Private 方法的单元测试 最近在添加一个新feature时,鉴于要给自己的代码一是增加代码的强壮性,二是增加代码测试的覆盖率.但是遇到了有些方法是 Private 的,但是在调 ...
- 利用java编写的盲注脚本
之前在网上见到一个盲注的题目,正好闲来无事,便用java写了个盲注脚本,并记录下过程中的坑 题目源码: <?php header("Content-Type: text/html;ch ...
- 品味性能之道<九>:利用Loadrunner编写socket性能测试脚本简述
一.概述 Loadrunner拥有极为丰富的工具箱,供予我们制造出各种奇妙魔法的能力.其中就有此次要讨论的socket套接字操作. 二.socket概述 ...
- Python 利用Python编写简单网络爬虫实例3
利用Python编写简单网络爬虫实例3 by:授客 QQ:1033553122 实验环境 python版本:3.3.5(2.7下报错 实验目的 获取目标网站“http://bbs.51testing. ...
- Python 利用Python编写简单网络爬虫实例2
利用Python编写简单网络爬虫实例2 by:授客 QQ:1033553122 实验环境 python版本:3.3.5(2.7下报错 实验目的 获取目标网站“http://www.51testing. ...
随机推荐
- 奇怪的Unrooted Tests错误
错误如图: 条件如下: Eclipse里的Maven工程. 使用JUnit4(这个是否必须不知,反正我的工程用的4) 修改某个Test类里的方法名,或者增加一个Test方法. 现象: 在MyEclip ...
- 【洛谷1967】货车运输(最大生成树+倍增LCA)
点此看题面 大致题意: 有\(n\)个城市和\(m\)条道路,每条道路有一个限重.多组询问,每次询问从\(x\)到\(y\)的最大载重为多少. 一个贪心的想法 首先,让我们来贪心一波. 由于要求最大载 ...
- 【BZOJ3123】[SDOI2013] 森林(启发式合并主席树)
点此看题面 大致题意: 给你一片森林,有两种操作:询问两点之间的第\(k\)小点权和在两棵树之间连一条边. 前置技能:树上主席树 做这道题目,我们首先要会树上主席树. 关于树上主席树,这有一道很好的例 ...
- 为项目创建podfile
由于写项目 不常用到,容易忘记,记录一下 第一步:新建一个项目: 第二步:打开终端,输入 cd 第三步:把项目拖入终端,(获取项目路径) 第四步:回车,输入 pod init (生成podfile 文 ...
- MAC 设置登录欢迎语
MacdeMacBook-Pro:etc mac$ cd /etc MacdeMacBook-Pro:etc mac$ cat motd 技术沉淀,空杯心态! _______ _______ _ __ ...
- 基于纹理内存的CUDA热传导模拟
原文链接 项目中有三个,第一个是全局内存,其余两个分别是基于1d和2d纹理内存.项目打包下载. 纹理内存是只读内存,与常量内存相同的是,纹理内存也缓存在芯片中,因此某些情况下,它能减少对内存的请求并提 ...
- C#装箱与拆箱的研究
在对这个问题展开讨论之前,我们不妨先来问这么几个问题,以系统的了解我们今天要探究的主题. 观者也许曾无数次的使用过诸如System.Console类或.NET类库中那些品种繁多的类.那么,我想问的是它 ...
- daemon函数实现原理 守护进程
linux提供了daemon函数用于创建守护进程,实现原理如下: #include <unistd.h> int daemon(int nochdir, int noclose); 1. ...
- Sum All Odd Fibonacci Numbers-freecodecamp算法题目
Sum All Odd Fibonacci Numbers 1.要求 给一个正整数num,返回小于或等于num的斐波纳契奇数之和. 斐波纳契数列中的前几个数字是 1.1.2.3.5 和 8,随后的每一 ...
- ajax全局变量的使用
var username; $.ajax({ type:"post", url:"a.action", data: {}, dataType: 'text', ...