在C++里写一个不能被继承的类

这是最近看到的一道面试题,最近是看了不少道面试题,C++里各种变态的问法。这道题算是比较正常的吧。在C++语言里,是没有类似Java里final class的概念的,但是学C++的人心里一定要相信,C++是万能的。于是有人给出了一种解法

代码我在下面再贴一下吧,不过著作权归原作者所有,向原作者表示敬意。

template <typename T> class MakeFinal

{

      friend T;

private :

      MakeFinal() {}

      ~MakeFinal() {}

};

class FinalClass: virtual public MakeFinal<FinalClass>

{

public :

      FinalClass() {}

      ~FinalClass() {}

};

这个方法行不行,行!请注意红色的部分,由于声明了T是友元类,所以可以访问自己的私有成员函数,当然也包括构造和析构函数;但是由于FinalClass是虚继承自MakeFinal,所以当有一个类ChildClass: public FinalClass时,会先调用虚基类MakeFinal的构造函数,由于调用者是ChildClass,所以无法调用。上述代码要是把virtual去调,则可以有ChildClass: public FinalClass,因为普通的继承是由子类调用父类的构造函数,向上调用,ChildClass的父类FinalClass是可以调用MakeFinal的构造函数的,所以这里虚继承是必须的。不然就无法实现一个不能被继承的类。

这个方法有没有局限,答案是有。上述代码第一个红色的部分,只要在支持c++0x标准的编译器里才能编译通过,GCC 4.4就算是加上-std=c++0x也不能通过,因为4.4只是部分支持了c++0x的标准。是不是就不能做出一个在GCC 4.4里可以用的FinalClass了?非也,C++是万能的。嗯,你在friend后面直接加个class后,GCC会报有编译错误,此路是不通的。客官就别试了。

我们定义另一个结构体:

template<typename T>

struct Clazz

{

      typedef T Type;

};

然后把原来的FinalClass略加修改:

template <typename T> class MakeFinal

{

      friend class Class<T>::Type;

private :

      MakeFinal() {}

      ~MakeFinal() {}

};

OK,在GCC里可以编译通过了,并且虚继承了MakeFinal的类是无法再被继承的了,会在编译的时候报错。

小结,其实我们的目的就只有一个,把基类或是基类的基类的构造函数变成私有的。这样子类再继承这个类是,因为无法调用构造函数,就会产生编译时错误,自然也就没有办法继承了。

上述在GCC里能用的办法也不是我想出来的,出处在这里

这篇文章也发表在AgilePHP,去看看

在Godaddy的主机上配置CodeIgniter

之前在CodeIgniter上部署过一个小的CodeIgniter的应用,参考了这篇文章,当时顺利的完成了部署运行的任务。主要是因为在Godaddy的虚拟主机上使用rewrite模块产生的问题,原因不知道,只知道一种解决问题的办法。主要的步骤为:

在config.php里修改配置,使用QUERY_STRING的方式来解析URL

$config['uri_protocol'] = "QUERY_STRING";

然后,修改.htaccess文件,使其内容为如下所示:

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php?$1 [L]

这样,某个请求,如http://www.example.com/blog/view/123 ,实际上会被解析成http://www.example.com/index.php?blog/view/123 ,但是,假如我使用的请求必须通过GET方法传参数呢?这种解决方案就不能解决问题了。如http://www.example.com/index.php?blog/view/123?from=1009&author=bbiao ,这个时候就无法通过parse_str($_SERVER['QUERY_STRING'], $_GET);的方法来获得GET的数据了。但是我们可以观察到$_SERVER['REQUEST_URI']里保存了blog/view/123?from=1009&author=bbiao的值,OK,解析一下这个数据就可以了。代码如下:

$arr = explode(‘?’, $_SERVER[‘REQUEST_URI’]);
parse_str($arr[1], $_GET);

另外说一句,由于CI里是把$_GET的数据清空的,所以才有了以上的这些说法,CI本身是不推荐使用GET来传递参数的,但有时候又不得不用,比如使用OAuth的时候,别人回调你的接口的时候都是这样传的,你能怎么办呢?事情总有解决办法的,现在我的程序在Godaddy上跑的一切正常。

这篇文章也发表在AgilePHP上,你可以点击这里查看。

Xen Cloud Platform 0.1.1

Xen Cloud Platform 是一个基本Xen虚拟化技术的云计算基础平台,这半年一直在使用另外一个商业版本XenServer,少对XCP有所关注,今天看了它的官方主页,XCP今年有一个新的版本发布,版本号是0.1.1,我去年使用XCP的时候,其版本还是0.1,这里对新版本做一个简单的介绍。

版本0.1.1发布于今年1月18号(汗,现在才知道),新增加的功能包括:

  • Openvswitch
  • XCP Console Documentation
  • VNC Console Proxy and Web Front-End
  • Standalone Front-End – *openxencenter*
  • VM Lifecycle Queuing Deadlock Fixed
  • Rare Post-Fork() Spinning XAPI Process Fixed
  • Active Directory Authentication Fixes
  • Memory Ballooning Fixes

其中描述的单独的前端就是XenCenter的一个开源Python实现,试用了一下,与XenCenter 5.5还是有一定差距的,但是总算是有一个前端可以选择了,之前用xe cli和Web管理太痛苦了,详细信息和下载,可以到XCP的主页查看。

这篇文章也发表在AgilePHP上,点击查看。

周六小记

CHB想换手机,看中了HTC Magic(G2),我跟他说中关村水太深,你先去论坛上泡一段时间,摸一下底细再买,给他推荐了两个论坛机锋网安卓网,其实我也没买过水货手机,不过想想这两家国内关注Android的论坛应该算是最大的两这了,看一看应该有收获。

昨天他说,看得差不多了,也查了一下报价,今天准备入手。早上打我电话,到实验室另一个在西安买过G2的小学弟把今天一些村里商家的报价打出来,最低1530,我差点喷了,不过同一店家的报价也有2000多的,于是觉得这一定是水价,肯定只是想吸引我们过去。

果然不出我所料,上午逛了几家在网上报价低的商家,全部是出了2100以上的价格,最贵的有报2300的,比我心理价位2000贵了许多。而且这种形势,在大部分商家都报高价的情况下,那些报低价的货的质量就十分令我们担忧。最后挑来挑去未果,中午先去吃饭,在大食代解决了午饭,期间遇到了俞敏洪,合照一张,人还挺和蔼,身边带了个保镖。

下午继续,基本上定在了一这机锋认证的卖家那,贵是贵一点,也就一百块钱左右,但是能买个放心。出价2230,加一张sandisk4G的行货卡,贴膜,一共2310,10钱都不给便宜。之后便是装系统,刷机什么的。搞定的时候也三点多了,期间有个小朋友以十分快捷的速度买了Moto Milestone。

然后在回来的路上等车的时候,青年工社的人给我打电话,小黑修好了。我去取,换了主板,而且是蓝快的备板,全新的。交了500块钱有偿保修的费用,心里也算比较开心吧。终于修好了,周二送过去的,速度还可以。

无法定位程序输入点DwnHintDxUpdate的解决办法

登陆飞信时,出现“无法找到入口”提示:
无法定位程序输入点DwnHintDxUpdate于动态链接库USER32.dll上。

曾经用Windows Vista的时候,上飞信就遇到过这个问题,现在在Windonws 7上用飞信2010,也有这个问题,但可恶的是点击了确定以后,提示还是不断的弹出来。Google了一下,发现了解决办法,有两个:

  1. 把安装目录下的dwmapi.dll 删掉
  2. 将%windir%system32dwmapi.dll复制到飞信的安装文件夹,覆盖原文件

问题是这个dll飞信带着是为了什么?为了在Windows Vista以下版本的机器上正常工作么?那为什么不测测在Windows Vista以上的机器上是否正常,或者安装的时候就检测一下,如果是Windows Vista以上版本的系统,就不要拷贝这个dll了。

这篇文章也发表在AgilePHP上,现在去看看,无法定位程序输入点DwnHintDxUpdate的解决办法

大数据量系统

这半个月一直在忙,忙着改程序,做实验,原来的系统的处理能力是10^4/10^5,我现在需要处理的数据量是10^6/10^7。原来正常的程序却出现了各种各样的异常,最明显的问题有两个,一个是OutOfMemory,一个是Connection Reset。

前一个问题有很多种不同的解决方法,就是增加机器的物理内存,调优jvm的启动参数,如果这些都解决不了问题,那就是程序本身的问题。我遇到的最多的就是BufferedReader溢出、ArrayList的不正确使用。这些问题都解决了还是会发现莫明其妙的溢出的话,还是增加物理内存吧。jvm虽然有垃圾收集机制,但是如果程序设计的初衷就没有为大数据量的数据考虑过的话,内存消耗真是件杯具而且及其不好解决在问题,特别是在code base有10^5级别的时候。

后一个问题,目前我还没有找到好的解决办法,目前能想到的,就是增加发送和接收缓存,平滑发送的速率,可是16*16的链接还是会莫明其妙的断掉。

郁闷了!还是需要再接再厉,外围的方案解决不了问题的话,只能去动核心的代码了。身边也没有有经验的人可以请教,我自己现在倒是对大数据量、巨数据量系统的可伸缩性和性能有了很强的兴趣。

这篇文章也发表在AgilePHP上,快去看看,大数据量系统

Apple iPad

虽然自己一直没有用过Apple的产品,但是对他的新产品发布都有关注,乔大爷北京时间今天凌晨发布了苹果定位在iPhone与MacBook之前的产品,iPad,这个名字并不出人意料之外,之前也有猜测叫做iSlate,我更倾向于这个名字。先上张图:

201012841519

外观上给人的印象真的就是一大号的iPod Touch,而且边框也太厚了吧?难道就是为了配合最下面的那个Home键么?

再说说他的配置:

  • Display: 9.7 inch IPS
  • Weight: 1.5 lbs
  • 0.5 inches thin
  • Battery life: 10 hours
  • Accelerometer and Compass
  • Speaker, Microphone, and 30 pin connector
  • WiFi 802.11n
  • Processor: 1GHz Apple A4 chip
  • Storage: 16-64GB Flash
  • Full capacative multi-touch

作为一个娱乐休闲终端,我想这个配置应该是不错的了。但是就其本身定位而言,没有加入对Flash的支持,虽然他有一个很强的Safari浏览器,可是仍然没有办法使用很多网上由Flash展现的电影、游戏。集成Flash对于苹果来说不能难做,而是不想做,做了无异于就失去了iPad内容独家提供商的地位。

苹果想通过各种各样的终端(iPod,iPhone,iPad)来分发书籍、音乐、电影、游戏和应用程序,并且不准备跟其他人一起合作,这些终端的操作系统都是iPhone OS,这种战略会成功么?也许吧,苹果本身就是一家喜欢创建新规则的公司。

==eof==

这篇文章也发布在AgilePHP上,快去看看吧,Apple iPad

CentOS配置vsftpd遇到550错误的解决办法

安装vsftpd很简单:yum install vsftpd

启动vsftpd也很简单:service vsftpd start

默认情况下用root是无法连接的,你可以创建一个非root帐户登录,但是登录是可以登录,却没有办法创建或是上传文件。有人说,可以把SELinux关掉,可是这样未免也有点尺度太大了,其实是SELinux里的设置问题,只要修改相应的配置就可以了。

发现问题的方法:

# getsebool -a | grep ftp
allow_ftpd_anon_write –> off
allow_ftpd_full_access –> off
allow_ftpd_use_cifs –> off
allow_ftpd_use_nfs –> off
ftp_home_dir –> off
httpd_enable_ftp_server –> off
tftp_anon_write –> off

将红色字体部分的值改成on就可以了,设置的方法如下:

# setsebool -P ftp_home_dir 1

然后就可以上传文件,做你想做的事情了。

这篇文章也发表在AgilePHP上,去看看,CentOS配置vsftpd遇到550错误的解决办法

Refactor

为什么要重构?我不知道教科书是或是别人都会怎么讲,但是重构对我来说,基本上就是把一个糟糕的设计重新写一遍。那么,什么是我定义的两糟糕的设计?又怎么样来重写,并且期望能够达到一个怎么样的目的才算是一个好的重构呢?

糟糕的设计:

  1. 因为时间紧,任务重,没有进行设计,基本上是随心所欲的写出来的代码;
  2. 充斥着“if…else…”,打了无数的补丁,新增功能的时候,就得多增加判断条件;
  3. 代码变得越来越复杂,相同的代码出现在了不同的地方,修改一处,必须时刻记着也要修改别的地方

那怎么样来重写呢?完全抛弃以前的代码么?

  1. 完全抛弃以前的代码:之前的代码写得实在是太糟糕,没有任何可取之处。而且没有办法使用一些重构工具一进行梳理。我自己没有遇到过这种情况。每一小段代码还不至于写得面目全非,这应该算是代价相对较重的一种重构方法,与其说是重构,不如说是重新写。
  2. 使用之前的代码:之前的代码,小的部分还是可以使用的,将它们独立出来,形成单独的模块,并使用一定的模块调用机制(如使用事件机制、插件系统)等,来调合各个不同的模块之间进行谐调工作。

我希望能达到一个几样的效果呢?

  1. 简单的说,我比较追求系统的可扩展性(scalability & extensibility)、可维护性、较高的系统性能。
  2. scalability是期望在一个较大的数据集前,系统也可以有一个比较好的表现;
  3. extensibility是期望系统能够容易的增减功能;
  4. 可维护性是期望系统在需要做出修改的时候,可以更加方便;
  5. 较高的系统性能,这个就不必说了,谁都希望自己的程序跑得更快。

有些时候,做重构并不是一个简单的决定,因为你要做出更多的工作,还不一定能搞出一个可用的系统来,但是,有风险的事情,做成功了会收获很大的好处,大部分时间,我还是咬咬牙会去选择重构代码。

==eof==

这篇文章也发表在AgilePHP上,快去看看,Refactor

Nokia 5530XM

还是要跟小6说声对不起,把你摔坏了。

现在用的是小5,最近太忙,没时间折腾,原来是打算买个HTC Magic(G2),顺便还能试试在Android平台上做开发。可是时间实在是太仓促,买水货不做够功课我是不敢去买的,于是就买了Nokia 5530 Xpress Music。

到目前为此,我只装了Opera Mini 4.0和Opera Mini 5.2 Beta 2,以及UCWeb 7.0,Fetion for N97,QQ 2008 for Nokia 5800。前面的三款软件可以顺利安装,每一款都让人爱不释手,可以根据你个人的习惯来选择一个做为你的浏览器。同时,系统本身自带的浏览器也是不错的哟。

QQ 2008,去官网下,地址是http://mobile.qq.com/2008,手机型号选Nokia 5800XM
Fetion去官网下,地址是http://www.fetion.com.cn/download/mobileclient/,手机型号选N97

下下来了,OK,机器也连上WiFi了,想上飞信跟QQ,没门!这两个软件必须用GPRS连接,具体的设置方法是:

功能→设置→程序管理→已安装的程序→飞信(QQ)→选项→套件设置→接入点(移动梦网)

同时,我们要去掉那个无用的屏幕键盘,方法是:

功能→设置→程序管理→已安装的程序→飞信(QQ)→选项→套件设→屏幕键盘(关)→其它(默认)

与小五好好相处吧。

另外,连个WiFi的情况,可以正常使用手机自带的升级功能来升级系统,我真是肉牛满面呀!之前用小6从来没成功过。

如果你发现你的手机无法新建情景模式,或是无法自定义情景模式里的选项,那你可以尝试*#7370#这个功能!提醒:该功能会把你的手机彻底重置为出厂状态,所有联系人,以及设置信息都将不在。

这篇文章也发表在AgilePHP上,现在去看看,Nokia 5530XM