CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
可用分押宝游戏火热进行中... 专题改版:Java Web 专题
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  C/C++ >  C++ 语言

关于构造函数的问题

楼主wangyupacket()2004-09-03 15:42:49 在 C/C++ / C++ 语言 提问

我有C++类:  
     
          class   test  
          {  
            public:  
                    test();  
                    test(int   i);              
            private:  
                    int   _i;  
          };  
   
  有如下三个问题:  
  test::test()  
  {  
        this->test(9);    
  }  
  为何上一步不能编译通过?  
   
  test::test()  
  {  
        test::test(9);  
  }  
  为何不能得到正确的结果?  
  test::test()  
  {  
        this->test::test(9);  
  }  
  为何能得到正确的结果?  
   
  请讲述具体的原理,不胜感激!!!!!!  
  问题点数:0、回复次数:29Top

1 楼lifeixiao(李飞笑)回复于 2004-09-03 15:45:04 得分 0

markTop

2 楼plainsong(短歌)()回复于 2004-09-03 16:00:18 得分 0

我觉得这三种形式都应该是语法错误。构造函数不是test的成员函数,不能这样调用,只能在对象初始化时使用。可以编译的两种形式应该是编译器没有考虑到。  
   
  要实现你要的目的,应该只写一个构造函数:  
   
          class   test  
          {  
            public:  
                    test(int   i   =   9);              
            private:  
                    int   _i;  
          };  
  Top

3 楼iorchis(江楠)回复于 2004-09-03 16:15:10 得分 0

 
  test::test()  
    :_i(9)   //如欲将_i设为定值9  
  {  
  ...  
  }  
   
  test::test(int   i)  
    :_i(i)   //如欲用传入的参数设定_i的值  
  {  
  ...  
  }  
   
  Top

4 楼wwwooowww(熔点)回复于 2004-09-03 16:16:28 得分 0

我不知道你用的什么编译器,我在.net下时都有错误。  
  1、test::test()  
  {  
        this->test(9);    
  }  
  错误的原因:你的对象还没有构造,所以this指针没有指向。因为this是指向该类对象的指针,该类对象没有生成,故指针没有指向。  
   
  2、test::test()  
  {  
        test::test(9);  
  }  
  这样的用法只有类的静态成员才可以使用。你的构造函数不是静态的,所以错误。  
  而且调用一个类的函数,除了静态函数,和构造函数,都是某个对象调用的,也就是说都省略了this指针。在你的对象没有构造前,指针是错误的。  
   
  3、test::test()  
  {  
        this->test::test(9);  
  }  
  这个错误是前俩种的综合。我觉得不对。  
   
  Top

5 楼freshairfly(无知的虾米)回复于 2004-09-03 16:35:00 得分 0

不同意   plainsong(短歌)   的“构造函数不是test的成员函数”   这句话  
   
  Top

6 楼coolrick(拎壶冲)回复于 2004-09-03 16:40:40 得分 0

试试这样  
  test():test(9){}Top

7 楼wangyupacket()回复于 2004-09-03 16:42:25 得分 0

我觉得你们说的不对。  
  通过在构造函数中打印this指针和对象的地址比较,结果是一致的。说明在构造函数以前,this指针就已经建立。利用this->test::test(9),确实能达到类似于java中构造函数相互调用的目的。但是原理何在??  
  我的编译环境是VC++6.0Top

8 楼beyondtkl(大龙驹<*好久没来了,兄弟们好吧。*>)回复于 2004-09-03 16:42:44 得分 0

构造函数不是我们   在外面直接   显式调用的    
   
  而是   compiler调用的.  
   
  短歌说的   构造函数不是test的成员函数也就是这个意思..是成员函数的话   我们的对象就可以显式调用..Top

9 楼plainsong(短歌)()回复于 2004-09-03 16:47:22 得分 0

wwwooowww判断它们是语法错误是正确的,但理由是错误的。  
  >test::test()  
  >{  
  >       this->test(9);    
  >}  
  >错误的原因:你的对象还没有构造,所以this指针没有指向。因为this是指向该类对象的指  
  >针,该类对象没有生成,故指针没有指向。  
   
  在构造函数和析构函数中使用this是完全可以的,有些对象会在构造时把自己注册到某一个全局容器中而在析构时注销,这种作法是安全的。事实上在构造函数的函数体中的语句执行时,不仅this有效,this所指向的该类的数据成员也都已经构造完毕,可以通过this去访问:  
   
  class   test  
  {  
      int   i;  
  public:  
      test(int   init_i):i(init_i){cout   <<   this->   i;}//这里没什么问题。  
  };  
   
  >2、test::test()  
  >{  
  >       test::test(9);  
  >}  
  >这样的用法只有类的静态成员才可以使用。你的构造函数不是静态的,所以错误。  
  >而且调用一个类的函数,除了静态函数,和构造函数,都是某个对象调用的,也就是说都省  
  >略了this指针。在你的对象没有构造前,指针是错误的。  
   
  错。在非静态成员函数中用class::member的方式访问非静态成员函数是可以的,这时会把当前的this指针传进去:  
   
  class   test  
  {  
        int   _i;  
        void   set_i(int   i){   _i   =   i;}  
  public:  
        test(){   test::set_i(0);}  
  };  
   
  这种方法通常用于在基类同名成员函数被衍生类重载(overload)时来指明调用的是基类的成员函数,或是用来在调用虚成员阻止多态行为。而如果class就是当前的类,而mamber不是虚成员,它就相当于直接调用member。在本例中就相当于test(){set_i(0);}  
   
  两个理由都不正确,当然也就没有什么“综合”了。  
   
  其实正确的理由是:构造函数不能直接访问。构造函数没有名字,所以在编译this->test(9)或是test::test(9)时,编译器无法在test这个类的成员名字列表中找到它。错误提示信息应该是:“test不是test的成员”。  
   
  ISO/IEC   14883:1988   12.1.2  
  A   constructor   is   used   to   initialize   objects   of   its   class   type.   Because   constructors   do   not   have   names,   the   are   never   found   during   name   lookup;……Top

10 楼beyondtkl(大龙驹<*好久没来了,兄弟们好吧。*>)回复于 2004-09-03 16:47:47 得分 0

回复人:   coolrick(拎壶冲)   (   )   信誉:100     2004-09-03   16:40:00     得分:   0      
     
     
        试试这样  
  test():test(9){}  
       
     
  //   这样也达不到你的要求的   呵呵   因为这样是构造出一个临时对象   而不是你真正要构造的thisTop

11 楼freshairfly(无知的虾米)回复于 2004-09-03 16:51:27 得分 0

1、test::test()  
  {  
        this->test(9);    
  }  
  错误的原因:你的对象还没有构造,所以this指针没有指向。因为this是指向该类对象的指针该类对象没有生成,故指针没有指向。  
  -------------------------------------------------------------------------  
  该类的对象并不是“没有生成”而是“没有完全生成”。而“没有完全生成”并不意味着“什么都没有”。并且它是有指向的,比如:  
  this->_i   =   9;   //OK(就等价于   _i   =   9;   嘛,当然可以,呵呵)  
  不过因为“没有完全生成”所以使用起来要小心  
   
   
  2、test::test()  
  {  
        test::test(9);  
  }  
  这样的用法只有类的静态成员才可以使用。你的构造函数不是静态的,所以错误。  
  而且调用一个类的函数,除了静态函数,和构造函数,都是某个对象调用的,也就是说都省略了this指针。在你的对象没有构造前,指针是错误的。  
  -------------------------------------------------------------------------  
  并不是只有类静态成员才可以这样使用,这个用法无非是指明一个类域,因为在test类里,默认的类域就是test::,所以没必要,至于为什么不对呢,我猜测是因为test(int   i)这个构造函数还没有生成。(有点编译器可能这样用法不规范,所以认为是错误的,但有的编译器是不报错的,比如VC6.0和Dev   C++4.9.6.0)  
   
   
  至于第三种为什么正确了呢?实在是想不出来为什么(可能是不同编译器实现手法不一样吧,VC6.0上是可以的并且是正确的,Dev   C++4.9.6.0就编译通不过了)。Top

12 楼xteaj(半桶水)回复于 2004-09-03 17:02:59 得分 0

构造函数是一种很特殊的成员函数。你注意到了没有,构造函数没有返回类型,  
  void也不是,因为构造函数实际上是一段类似inline函数的东西,直接插入函数  
  所在位置,不过因为你不能直接往对象私有成员写数据,而构造函数可以。所以  
  构造函数并没有实际的地址,某种意义上说,连函数都不能算。Top

13 楼plainsong(短歌)()回复于 2004-09-03 17:03:39 得分 0

 
  在Java中构造函数可以互调,这Object   Pascal也可以(据说Borland参与了Java语言的设计),但这没什么必要性。你完全可以把两个构造函数都要有的代码写到一个私有的成员函数中,然后在两个构造函数中都去调用。  
   
  注意一点:C++中构造函数对基类和数据成员的构造函数的调用是强制性的,而Java和Object   Pascal不是。在C++中允许构造函数互相调用必然导致对基类和数据成员的重复构造,而这将是一个灾难。  
   
  后两种方法都在VC中编译通过并且有一种可以达到楼主的目的,这并不能说明什么,只能说VC6对标准的支持不好,同时test::test()与this->test::test()得到不同的结果也是编译器的明显错误。在我BCC5.6.4中只有第二种可以通过编译,但并不能达到楼主的目的;wwwooowww说在.net都不能通过编译说明.net的编译器实现的比较出色。Top

14 楼wangyupacket()回复于 2004-09-03 17:22:17 得分 0

我觉得对象的生成可不可以这样解释:  
   
  1.   test   t;                                         //为对象分配存储空间。  
  2.t.test()   =   test(t);                   //调用构造函数初始化对象成员。  
  但是我觉得test::test()好像产生了一个临时对象,这个临时对象的空间是怎样分配的?Top

15 楼plainsong(短歌)()回复于 2004-09-03 17:26:40 得分 0

我感觉不大对头。从BCBX的编译和运行结果来看,test::test()确实生成了一个临时对象,但要做到这一点正规的语法应该是test(),test::test()是解释不通的……Top

16 楼bm1408(向va_list学习~不用VC好多年~)回复于 2004-09-03 17:34:01 得分 0

构造函数我们是无法显示的调用的!Top

17 楼wangyupacket()回复于 2004-09-03 17:40:54 得分 0

使用test()或是test::test()我觉得效果应该是一样的,但关键是为什么要产生一个临时对象?而且好像不止一个编译器都是这样的!!!Top

18 楼plainsong(短歌)()回复于 2004-09-03 17:46:26 得分 0

test()和test::test()在语法上是不一样的,用test()可以定义临时对象,这里的test是类型名。用这种方法定义临时对象是很常用的手段:  
  class   comp  
  {  
  public:  
      bool   operator()(const   string&   x,   const   string&   y)  
      {return   x.size()   <   y.size();}  
  };  
  vector<string>   strlist;  
  ...  
  sort(strlist.begin(),   strlist.end(),   comp());//这里创建了一个comp类型的临时对象作为实参。  
   
  但test::test()中的test::test无论如果不能解释成一个类型:test不是一个namespace,也没有名为test的嵌套类型,那么test::test()如何解释就是一个问题了。Top

19 楼comebaby(游民)回复于 2004-09-03 18:46:40 得分 0

高深!!关注中。。。Top

20 楼nicknide(封月翔天)回复于 2004-09-03 19:50:06 得分 0

大家说了很多,我来说一个最重要的原因吧:  
  标准C++规则中,就不允许我们直接调用构造函数,但是可以直接调用析购函数  
  class   A  
  {  
  public:  
  A();  
  ~A();  
  };  
   
  A   a;  
  a.A();//error,user   cann't   invoke   the   constant   funcation  
  a.~A();//OK,No   propram  
   
   
   
  还有,有人说是this指针的问题,其实不是,因为在调用构造函数的时候,比如VC,用ecx寄存器传过来一个this的指针,这个地址是有效的。  
   
  如果你希望实现这个this->A();这个功能,有办法的,可以这样做  
  #include   <new>  
  using   namespace   std;  
  class   A  
  {  
  A(){     new   (this)   A;}  
  A(int   i);  
  };  
   
  这个定点构造的方法就可以让你随心所欲了,不过记住,这个地方的new   不是分配内存,所以绝对不能用delete删除掉,否则你自己看吧……Top

21 楼nicknide(封月翔天)回复于 2004-09-03 19:52:59 得分 0

关于定点构造,有这样一种用法:  
  class   A  
  {  
  public:  
  A(const   A&);  
  A&   operator   (const   A&   other)  
  {  
  ~A();  
  new   (this)A(other);  
  }  
  };  
   
   
  哈哈,不过这样做不太好哦,标准不建议这样做,虽然这样做是完全语法正确的。建议,一定不要这样哦Top

22 楼nicknide(封月翔天)回复于 2004-09-03 20:00:50 得分 0

对了,我发的第一个帖子有手误,抱歉抱歉,这里改一下,然后把例子补充完整  
  #include   <new>  
  using   namespace   std;  
  class   A  
  {  
  public:  
  A(){     new   (this)   A(3);}//this   line   is   changed  
  A(int   i):k(i){}  
  int   k;  
  };  
   
  int   main()  
  {  
  A   a1(3);  
  A   a2();  
  }  
  //是不是都是一样的结果了啊?  
   
  Top

23 楼renheihei(请大家注意:用DEV C++作为测试编译器!!!!!!!!!,vc++测试可能通不过!!!!!!!!)回复于 2004-09-03 20:09:42 得分 0

好问题!Top

24 楼languagec(各有所求)回复于 2004-09-03 20:40:35 得分 0

 
  Top

25 楼nicknide(封月翔天)回复于 2004-09-03 21:33:56 得分 0

汗,我再改(抱歉,今天有些头晕了,3天只睡了10个小时,请大家原谅了):  
  关于定点构造,有这样一种用法:  
  class   A  
  {  
  public:  
  A(const   A&);  
  A&   operator   =   (const   A&   other)//重载等于运算  
  {  
  ~A();  
  new   (this)A(other);  
  }  
  };  
  Top

26 楼coyprightbao(Mr'Bao)回复于 2004-09-03 21:47:03 得分 0

markTop

27 楼BluntBlade(信仰迷离·重构之道,在于Redo/Undo之间)回复于 2004-09-03 22:42:29 得分 0

我在某本C++名著中看到  
  obj.A::A();   //   重新对已经存在的对象进行初始化  
  这样的写样,而我自己也试验过,确实可以通过编译。但楼主给出的示例就没有试验过。Top

28 楼wangyupacket()回复于 2004-09-07 17:28:30 得分 0

我觉得短歌说的重复构造是一个问题,但是也要看基类的申明情况而定。最近参阅了《深入探索C++对象模型》,觉得写得非常好。上面对构造函数有详细的说明,感兴趣的朋友可以看一看。Top

29 楼wangyupacket()回复于 2004-09-13 20:16:37 得分 0

BluntBlade(无锋之刃·只留程序不留情)   看的是哪本名著,介绍一下:)Top

相关问题

  • 构造函数
  • 构造函数
  • 构造函数??
  • 构造函数
  • 函数构造
  • @@@@@@ 构造函数 @@@@@
  • WebService构造函数
  • 构造函数和析构函数
  • 构造函数是内联函数吗?
  • 构造函数与析构函数

关键词

  • .net
  • c++
  • 函数
  • 指针
  • 编译器
  • 编译
  • 语法
  • 数据
  • 构造
  • 调用

得分解答快速导航

  • 帖主:wangyupacket

相关链接

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

广告也精彩

反馈

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