CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
花落谁家,你作主! 盛大widget设计大赛英雄榜
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  C/C++ >  C语言

怎样定义一个基类,使其派生类只能通过new实例化?

楼主Fantasia(幻想曲)2002-04-18 22:34:52 在 C/C++ / C语言 提问

注意,不能对派生类的加以语言之外的限定。 问题点数:100、回复次数:24Top

1 楼wlz47(秋水沉舟)回复于 2002-04-18 22:56:48 得分 10

酱紫不知道合不合你的要求  
   
  class   base  
  {  
  private:  
  virtual   ~base()   {}  
  public:  
  base()   :   i(0){};  
   
  int   i;  
  };  
  //*  
  class   derived   :   public   base  
  {  
  public:  
  void*   operator   new(size_t)  
  {  
  return   new(derived);  
  }  
   
  };  
  //*/  
     
  void   main()  
  {  
  derived   d;       //   wrong  
  derived*   pd   =   new   derived;     //   OK  
  }  
  Top

2 楼wlz47(秋水沉舟)回复于 2002-04-18 22:58:52 得分 10

"注意,不能对派生类的加以语言之外的限定"  
   
  对不起,这句没看见,let   me   again   think   think.Top

3 楼wlz47(秋水沉舟)回复于 2002-04-18 23:02:19 得分 0

不重载继承类的new操作符好像也可以:  
  class   base  
  {  
  private:  
  virtual   ~base()   {}  
  public:  
  base()   :   i(0){};  
   
  int   i;  
  };  
   
  class   derived   :   public   base  
  {  
  public:  
  /* void*   operator   new(size_t)  
  {  
  return   new(derived);  
  }  
  */  
  };  
     
  void   main()  
  {  
  derived   d;       //   wrong  
  derived*   pd   =   new   derived;     //   OK  
  }  
   
  Top

4 楼anrxhzh(百宝箱)回复于 2002-04-18 23:05:00 得分 10

More   Effective   C++   Item   27:     Requiring   or   prohibiting   heap-based   objects   中讲得很透彻。  
   
  只需要将基类的析构函数声明为protected即可,例如:  
  class   HeapObject   {  
  public:  
      //constructor  
      ...  
   
      //   pseudo-destructor   (a   const   member   function,   because  
      //   even   const   objects   may   be   destroyed)  
      void   destroy()   const   {   delete   this;   }  
  private:  
      ~HeapObject();  
  };  
  Top

5 楼wlz47(秋水沉舟)回复于 2002-04-18 23:10:43 得分 10

还是不行,delete   继承类对象指针时,因为继承类对象没有权限调用基类的析构函数而导致derived对象不能析构,故无法通过编译。  
   
  分特,let   me   again   think   think.Top

6 楼wlz47(秋水沉舟)回复于 2002-04-18 23:18:01 得分 0

难啦Top

7 楼wlz47(秋水沉舟)回复于 2002-04-18 23:41:05 得分 10

用设置某成员函数存取权限的方法恐怕不太可能吧。  
  因为你的要求是矛盾的,要达到你的要求恐怕非得对继承类动手脚才行Top

8 楼prototype(原型)回复于 2002-04-19 04:46:44 得分 10

anrxhzh(百宝箱)   is   right.     make   your   ctors   private/protected.   this   is   a   routine   method   to   demand   that   objects   can   be   only   created   in   heap.Top

9 楼heming_zs()回复于 2002-04-19 09:05:38 得分 5

其实不难,将基类的constructor   function   设为private,然后重载new操作副,  
  class   HeapObject{  
      private:  
        HeapObject();  
      public:  
        virtual   ~HeapObject();  
        HeapObject   *   operator   new(size_t){this=(HeapObject*)malloc(sizeof(HeapObject);return   this;}    
  }  
   
  Top

10 楼anrxhzh(百宝箱)回复于 2002-04-19 10:13:29 得分 5

to   wlz47(秋水沉舟):  
   
  我给的示例代码有误,要将  
  private:  
      ~HeapObject();  
  改为  
  protected:  
      ~HeapObject();  
   
  很抱歉,给你带来了麻烦。Top

11 楼LionEagle(LionEagle)回复于 2002-04-19 10:59:29 得分 10

to   anrxhzh(百宝箱):  
   
  ~HeapObject不能设为virtual,否则用new也会被阻止,因为~HeapObject没有定义,而建立vtbl需要~HeapObject的定义Top

12 楼prototype(原型)回复于 2002-04-19 12:10:18 得分 5

sorry.   didn't   read   'anrxhzh(百宝箱)'s   posts   carefully.  
   
  correct:   it   should   be   'constructor'   (not   destructor)   that   should   be   declared   as   private/protected.Top

13 楼anrxhzh(百宝箱)回复于 2002-04-19 14:26:32 得分 5

More   Effective   C++   Item   27:     Requiring   or   prohibiting   heap-based   objects   中介绍的方法只能针对单个类,无法针对整个类层次,下面是我给出的完整示例:  
   
  class   HeapObject   {  
  public:  
  //constructor  
  //...  
  //   pseudo-destructor   (a   const   member   function,   because  
  //   even   const   objects   may   be   destroyed)  
  void   destroy()   const{   delete   this;   }   ;  
  protected:  
  virtual   ~HeapObject(){};  
  };  
   
   
  class   A:public   HeapObject{  
  };  
   
  int   main()  
  {  
  //HeapObject   h; //compile   error  
  HeapObject   *   p   =   new   HeapObject;  
  p->destroy();  
   
  A   a; //   ok  
  return   0;  
  }  
   
  当然,如果把构造函数声明为protected\private也是一样的,不过由于构造函数可能不止一个,所以没有上面的方法简洁。  
   
  好像很难找出针对整个类层次的通用方法。Top

14 楼Fantasia(幻想曲)回复于 2002-04-20 02:14:36 得分 0

多谢各位的热心讨论!  
   
  其实单个类要控制只能在堆上分配不难,难的是要通过基类控制其子类也只能在堆上分配,anrxhzh(百宝箱)   上面的代码并没有达到要求。  
   
  关于限定条件,就是说不能要求派生类如何声明自己的构造函数、析构函数,也不能假定它通过一个destroy函数销毁(最好是通过delete),唯一的要求就是它要从指定的基类派生。这一点上,wlz47(秋水沉舟)理解是很正确的。他没有找到解,我也趋向认同无解。但是否能够确认这一点,还需要各位仁者见仁、智者见智了。帖子我会晚两天再结。Top

15 楼tang1975(tangtang)回复于 2002-04-20 10:42:17 得分 0

无解  
   
  or   template?    
  Let   me   install   Chinese   IME   first:)Top

16 楼hongbo_liu(bobo)回复于 2002-04-22 13:57:49 得分 0

gzTop

17 楼elvahuang(熊熊)回复于 2002-04-22 14:16:29 得分 0

不懂??!!为什么可以?  
  TO   wlz47(秋水沉舟)    
  ?????????????????????????  
  愿哪位高手说说?Top

18 楼elvahuang(熊熊)回复于 2002-04-22 14:21:29 得分 0

还有就是将析构函数私有化?????什么意思??  
  在More   Effictive   C++   中有讲?  
  Top

19 楼lengkuazhong()回复于 2002-04-22 15:36:33 得分 0

哪有Effective   C++Top

20 楼Fantasia(幻想曲)回复于 2002-04-23 23:46:06 得分 0

看来没人再感兴趣,作无解吧。Top

21 楼elvahuang(熊熊)回复于 2002-04-26 17:43:14 得分 0

#include   "iostream.h"  
   
  //after   refreshing's   problem  
  //base   class                   "re"   means   "refresh"  
   
  class   rebase  
  {  
  public:  
  virtual   ~rebase()  
  {  
  cout<<"in   rebase   destor"<<endl;  
  }  
  protected:  
  rebase()  
  {  
  cout<<"in   rebase   ctor"<<endl;  
  }  
  };  
   
   
  //derived   class  
  class   rederived:public   rebase  
  {  
  public:  
  ~rederived()                 //it   is   virtual   actually!!!!  
  {  
  cout<<"in   derived   destor"<<endl;  
  }  
  //void*   operator   new(size_t   size)  
  //{  
  // return   ;  
  //}  
      static   rederived*   MakeObject()               //here   must   show   to   our   user,if   they   get  
  {                                                           //the   return   pointer,they   must   delete   it   when    
  rederived*   pred=new   rederived;         //they   don't   want   to   use   it   wholely!!      
  return     pred;  
  }  
  private:  
  rederived():rebase()             //here's   base   must   be   visible!!!  
  {                                               //and   in   class   base   base()mustn't   be   visible   in   extern!!  
                                                          //so   base()   must   be   protected!!and   here   ":base()"may   not   write   out!!  
  cout<<"in   derived   ctor"<<endl;  
  }  
  };  
   
  //main  
  void   main()  
  {    
  // rebase   b;                                     is   wrong!!  
  // rederived   d;                               is   wrong!!    
  rederived*   pd=rederived::MakeObject();  
  delete   pd;  
  }  
   
   
   
  #include   "iostream.h"  
   
  //after   refreshing's   problem  
  //base   class                   "re"   means   "refresh"  
   
  class   rebase  
  {  
  public:  
  virtual   ~rebase()  
  {  
  cout<<"in   rebase   destor"<<endl;  
  }  
  protected:  
  rebase()  
  {  
  cout<<"in   rebase   ctor"<<endl;  
  }  
  };  
   
   
  //derived   class  
  class   rederived:public   rebase  
  {  
  public:  
  ~rederived()                 //it   is   virtual   actually!!!!  
  {  
  cout<<"in   derived   destor"<<endl;  
  }  
  //void*   operator   new(size_t   size)  
  //{  
  // return   ;  
  //}  
      static   rederived*   MakeObject()               //here   must   show   to   our   user,if   they   get  
  {                                                           //the   return   pointer,they   must   delete   it   when    
  rederived*   pred=new   rederived;         //they   don't   want   to   use   it   wholely!!      
  return     pred;  
  }  
  private:  
  rederived():rebase()             //here's   base   must   be   visible!!!  
  {                                               //and   in   class   base   base()mustn't   be   visible   in   extern!!  
                                                          //so   base()   must   be   protected!!and   here   ":base()"may   not   write   out!!  
  cout<<"in   derived   ctor"<<endl;  
  }  
  };  
   
  //main  
  void   main()  
  {    
  // rebase   b;                                     is   wrong!!  
  // rederived   d;                               is   wrong!!    
  rederived*   pd=rederived::MakeObject();  
  delete   pd;  
  }  
  这样行吗????  
   
   
   
  Top

相关问题

  • 初学者问题:一个基类有多个派生类,怎样在运行时根据不同的情况定义某个派生类的实例?(200分)
  • 初学者问题:一个基类有多个派生类,怎样在运行时根据不同的情况定义某个派生类的实例?(200分)
  • 派生类实例如何访问基类的虚拟方法?
  • 我派生的CPwdEdit类为什么提示为定义啊
  • 派生类的自定义属性问题(也许很简单)
  • 如何让自定义类的实例在堆上创建?
  • 关于自定义对象类型的实例化问题.
  • 怎样定义只能生成一个实例的类??
  • 怪事,派生类必须全部重定义基类同名虚函数?
  • 如何让一个成员不能在派生类中重新定义

关键词

  • c++
  • 函数
  • virtual
  • heapobject
  • 类
  • anrxhzh
  • wlz47
  • 百宝箱
  • derived
  • 析构

得分解答快速导航

  • 帖主:Fantasia
  • wlz47
  • wlz47
  • anrxhzh
  • wlz47
  • wlz47
  • prototype
  • heming_zs
  • anrxhzh
  • LionEagle
  • prototype
  • anrxhzh

相关链接

  • C/C++ Blog
  • C/C++类图书
  • C/C++类源码下载

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
北京创新乐知广告有限公司 版权所有, 京 ICP 证 070598 号
世纪乐知(北京)网络技术有限公司 提供技术支持
Copyright © 2000-2008, CSDN.NET, All Rights Reserved
GongshangLogo