现在的位置: 首页 > 综合 > 正文

C++中不能被继承的类

2013年11月06日 ⁄ 综合 ⁄ 共 3387字 ⁄ 字号 评论关闭

注意:下面的代码在VC2003上编译过,但在VC2005Beta版上会有问题。我想可能是试用版上有bug吧。

 

引出问题:

 

前天,一个同事给我看了一段代码,问我这段代码的涵义。乍一看我没有看出明堂。后来在与几个同事一起深入研究后发现了它的奥妙。这其中涉及到一些C++中的高级技术,很有意思。我把我们的分析作了一个总结,借这块宝地,拿出来供大家共同学习。原始代码如下(不知道她从哪里弄来的这么好的代码,在这里谢了!):

 

//file name: NoInherit.h

template <class T> class NoInherit_;

 

template <class T,template<class T> class A >

class NoInherit_< A<T> >

{

private:

       friend A<T>;

       friend T;

       NoInherit_(){}

};

 

template <class T>

class NoInherit:virtual public NoInherit_< NoInherit< T> >

{

public:

       typedef T type;

private:

       friend T;

       NoInherit():NoInherit_< NoInherit< T> >()

       {}

};

 

如果你是大虾一下子就看明白了这段代码,那么这篇文章对你就没有多大价值了,兄弟就不敢再耽搁你的时间了。如果你不能一下子看出来,那就让我来告诉你吧。它是一个不能被其它类继承的类模板。不信你试试……

 

按照下面的方法使用这个模板:

 

class CA:NoInherit<CA>

{

       //……

};

 

这个类CA不能再被其它类继承了.像这样

Class CB:CA

{

 

}

//error……编译会出错。提示不能访问NoInherit_的私有构造函数。

 

那么这个类模板是怎么样达到“不让其它类继承”的目的的呢?也许你已经看出来了。它是通过私有构造函数和虚拟继承来实现的。在我分析这个模板的过程中我思考过下面这几个问题:

1、  有哪些方法能实现“不让其它类继承”呢?

2、  为什么要用到friend A<T>;

3、  虚拟继承是怎么一回事?为什么在这里要使用虚拟继承呢?

4、  NoInherit_friend A<T>好理解,friend T怎么理解?

下面我就这几个问题展开讨论。

 

有哪些方法实现“不让其它类继承”

      

我们知道,子类继承父类,肯定会做的事情是:调用父类的构造函数(注意:子类不一定会调用父类的析构函数。为什么?自己想去吧!卖点拐子)。我们只要父类的构造函数是private的,子类想继承,没门儿!

       “不让其它类继承”就这么简单。是的,就这么简单!

       看官一定会问,既然这么简单,上面的代码为什么那么复杂呢?别急别急,待我下面慢慢道来……

       我们先分析下面几种情况:

A) 单件(single)模式

//single.h

class CSingle

{

public:

static CSingle *CreateInstance() ;

static void DeleteInstance() ;

……

private:

static CSingle *m_pSingle;

Csingle(){};

Csingle(Csingle&){};

};

 

//single.cpp

#include “single.h”

CSingle * CSingle ::m_pSingle = NULL;

CSingle * CSingle ::CreateInstance()

{

If(!m_pSingle)

m_pSingle = new Csingle;

       return m_pSingle;

}

CSingle :: DeleteInstance ()

{

delete m_pSingle;

:m_pSingle = NULL;

}

 

       它能够实现“不让其它类继承”,但很显然这种方式不好,它只能有一个实例。

那么下面这样呢?

class CExample

{

public:

       CExample* CreateInstance()

{

return new CExample;

}

private:

       CExample();

CExample(CExample&);

};

      

       网上很多人提到这种方法。我个人也认为这个方法可行。但是这不是最理想的方法,因为这种方法限制了CExample对象的创建:new CExample CExample  example

 

B)http://springsun.bokee.com/218785.html上提供了下面这种方法。
// Usable.h

class Usable;

class Usable_lock

{

     friend class Usable;

private:

     Usable_lock() {}

     Usable_lock(const Usable_lock&) {}

};

       

class Usable : public virtual Usable_lock

{

// ...

public:

     Usable();

     Usable(char*);//这是为什么没有明白。

     // ...

};

       

Usable a;

class DD : public Usable { };

DD dd;  // error: DD::DD() cannot access

            // Usable_lock::Usable_lock(): private member

    //(参见《The Design and Evolution of C++》,11.4.3) 

 

这跟上面一开始给出的代码原理是一样的。只不过上面将其模板化了。我个人推荐这里给出的方法。

       下面的讨论,如果你看最上面的代码费劲,看这里的代码好了。我也将以这里的代码为例进行说明。

 

为什么需要friend class

      

当创建Usable对象时需要调用Usable_lock的构造函数,而Usable_lock的构造函数是私有的,所以friend class Usable;是必要的。

 

虚拟继承

      

说老实话,我以前做项目没有使用过这个东西。这次正好有机会,仔细研究了一下。

从《C++程序设计语言(特别版)》和《c++_primer》中可以知道虚拟继承是一项专为解决多继承中的一个问题的。看下面的代码:

//非虚拟继承

class Base

{

public:

       Base()

       {

              cout<<"Base construct"<<endl;

       }

};

 

class CA: public Base

{

public:

       CA()

       {

              cout<<"CA construct"<<endl;

       }

};

 

class CB: public Base

{

public:

       CB()

       {

              cout<<"CB construct"<<endl;

       }

};

 

class CC:public CA,public CB

{

public:

       CC()

       {

              cout<<"CC construct"<<endl;

       }

};

 

int main()

{

       CC tt;

       getchar();

       return 0;

}

//虚拟继承

class Base

{

public:

       Base()

       {

              cout<<"Base construct"<<endl;

       }

};

 

class CA: virtual public Base

{

public:

       CA()

       {

              cout<<"CA construct"<<endl;

       }

};

 

class CB: virtual public Base

{

public:

       CB()

       {

              cout<<"CB construct"<<endl;

       }

};

 

class CC:public CA,public CB

{

public:

       CC()

抱歉!评论已关闭.