如何利用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. ...
随机推荐
- nvm安装nodejs(安装在非系统盘内)
在使用nodejs时有时需要不同的版本之间进行切换,所以就用到了版本管理工具nvm,在windows系统下用的是nvm-windows,这里选择的是nvm-noinstall.zip免安装版本(需要配 ...
- java Vamei快速教程06 组合
作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 我们已经尝试去定义类.定义类,就是新建了一种类型(type).有了类,我们接着构造 ...
- Internationalization(i18n) support in SAP CRM,UI5 and Hybris
i18n(其来源是英文单词 internationalization的首末字符i和n,18为中间的字符数)是"国际化"的简称.对程序来说,在不修改内部代码的情况下,能根据不同语言及 ...
- 【BZOJ1857】传送带(分治经典:三分套三分)
点此看题面 大致题意: 一个二维平面上有两条传送带\(AB\)和\(CD\),\(AB\)传送带的移动速度为\(P\),\(CD\)传送带的移动速度为\(Q\),步行速度为\(R\),问你从\(A\) ...
- geoWithin查询 多边形查询
$geoWithin查询 形状的表示 .$box:矩形,使用 {$box:[[<x1>,<y1>],[<x2>,<y2>]]}表示 都是坐标,第一个坐标 ...
- Count Numbers(矩阵快速幂)
Count Numbers 时间限制: 8 Sec 内存限制: 128 MB提交: 43 解决: 19[提交] [状态] [讨论版] [命题人:admin] 题目描述 Now Alice want ...
- install cmake,install torch7
cmake http://blog.csdn.net/jesse__zhong/article/details/21290675 torch7 http://wanghaitao8118.blog.1 ...
- Oracle 表的连接方式
1. 连接说明 ① Oracle一次只能连接两个表.不管查询中有多少个表,Oracle 在连接中一次仅能操作两张表. ② 当执行多个表的连接时,优化器从一个表开始,将它与另一个表连接:然后将中间结果与 ...
- Java十进制转成二进制 八进制 十六进制
int a = 357;//十进制转成二进制System.out.println(Integer.toBinaryString(a)); package com.swift; import java. ...
- 【Python学习之九】asyncio—异步IO
asyncio 这是python3.4引入的标准库,直接内置对异步IO的支持.asyncio的编程模型就是一个消息循环.从asyncio模块中直接获取一个EventLoop的引用,然后把需要执行的协程 ...