100-59

59.不能被继承的类(语法)。
题目:用C++设计一个不能被继承的类。

分析:这是Adobe公司2007年校园招聘的最新笔试题。
这道题除了考察应聘者的C++基本功底外,还能考察反应能力,是一道很好的题目。

思路:

这道题,初看起来比较奇葩。对于我这种新手来说真的是这样的。当我第一眼看到这个题目的时候,基本上是没有思路的,后来我想了下,貌似在Effective c++上看到过类似的说明,说是如果不想用编译器为你自动生成的一些函数,就要明确的指明出来。它上面说的方法就是将这些个函数声明为私有函数。于是,我就想到,如果将某个类的构造函数和析构函数都声明为私有的话,那么如果有新的类对其进行继承,在声明新的变量时,由于父类的构造函数无法调用,编译器就会报错。这是非常好的 ,因为让错误出现在编译阶段远远要好于让其出现在运行时。。。于是,说干就干,只要简单的将构造函数和析构函数都声明为私有就行了。

但是,菜鸟就是菜鸟,觉得这么一道题难道就是这样就解决了?不自信的又查看了july大神的解答。得到了这么一个参考:

// Define a class which can't be derived from 
template <typename T> class MakeFinal 
{ 
      friend T; 
private: 
      MakeFinal() {} 
      ~MakeFinal() {} 
};
class FinalClass2 : virtual public MakeFinal<FinalClass2> 
{ 
public: 

      FinalClass2() {} 
      ~FinalClass2() {} 

};
于是乎当我们定义这么一个子类时,会编译出错:


class Try : public FinalClass2 
{ 

public: 
      Try() {} 

      ~Try() {} 
};
 这个类使用起来和一般的类没有区别,可以在栈上、也可以在堆上创建实例。尽管类MakeFinal<FinalClass2>的构造函数和析构函数都是私有的,但由于类FinalClass2是它的友元函数,因此在FinalClass2中调用MakeFinal<FinalClass2>的构造函数和析构函数都 
 不会造成编译错误。 但当我们试图从FinalClass2继承一个类并创建它的实例时,却不同通过编译。由于类FinalClass2是从类MakeFinal<FinalClass2>虚继承过来的,在调用Try的构造函数的时候,会直接跳过FinalClass2而直接调用MakeFinal<FinalClass2>的构造函数。非常遗憾的是,Try不是MakeFinal<FinalClass2>的友元,因此不能调用其私有的构造函数。  
 基于上面的分析,试图从FinalClass2继承的类,一旦实例化,都会导致编译错误,因此是FinalClass2不能被继承。这就满足了我们设计要求。 
 


你可能感兴趣的:(100-59)