找回密码
 FreeOZ用户注册
查看: 5000|回复: 33
打印 上一主题 下一主题

[论坛技术] C++找茬,找出代码中存在的问题

[复制链接]
跳转到指定楼层
1#
发表于 26-1-2012 02:38:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?FreeOZ用户注册

x
那试试找出代码的问题,给出你理由。
class X
{
public:
    virtual int SomeFun() = 0{ return 1;}
    void AnotherFun()const
    { 
         v = 100UL;
         printf("%d",v,v);
    }
private:
    unsigned long v;
};
class Y : public X
{
public:
    Y() : p( new int ){}
     ~Y(){ delete p;}
     Y& operator =(Y y)
     {
           *p = *y.p;
     }
private:
    int* p;
};
void Delete(const X* x)
{
    delete x;
}

void Test()
{
    Y* y1 = new Y;
    Y y2 = *y1;
    Delete(y1);
}

评分

参与人数 1威望 +20 收起 理由
MillerYang + 20 你太有才了!

查看全部评分

回复  

使用道具 举报

2#
发表于 26-1-2012 14:53:02 | 只看该作者
我怎么觉得到处都是问题阿,首先就是看不懂 ,怎么SomeFun后面都没用到过,定义这个纯虚函数有什么意义阿?

v = 100UL; 这句也不理解,我怎么看着像语法错误

AnotherFun() 是个const函数,好像不能访问 v阿 ?

     Y& operator =(Y y)
     {
           *p = *y.p;
     }
这个为啥没有return语句阿?如何返回 Y&的?

void Delete(const X* x)
{
    delete x;
}
这个*x是const的,能被delete吗?不懂

还有Delete(y1)这句,是不是会造成内存泄漏阿?

SomeFun()后面没再定义过,那Y应该也是个虚类了,好像不能生成object,是不是这样啊?

我是c++菜鸟,最怕这种抽象的程序了
回复  

使用道具 举报

3#
 楼主| 发表于 27-1-2012 00:53:34 | 只看该作者
原帖由 四香油饼 于 26-1-2012 12:53 发表
我怎么觉得到处都是问题阿,首先就是看不懂 ,怎么SomeFun后面都没用到过,定义这个纯虚函数有什么意义阿?

v = 100UL; 这句也不理解,我怎么看着像语法错误

AnotherFun() 是个const函数,好像不能访问 v ...


就是有很多问题,所以才让找的。
回复  

使用道具 举报

4#
发表于 27-1-2012 13:32:19 | 只看该作者
  1. class X
  2. {
  3. public:
  4.     //an additional virtual ~X() {} needed here
  5.     virtual int SomeFun() = 0{ return 1;}  //pure virtual function shouldn't contain implementation
  6.     void AnotherFun()const
  7.     {
  8.          v = 100UL; //can't change member value in const method
  9.          printf("%d",v,v); //2 v with 1 '%d'
  10.     }
  11. private:
  12.     unsigned long v;
  13. };
  14. class Y : public X
  15. {
  16. public:
  17.     Y() : p( new int ){}  //p(new int(0))
  18.      ~Y(){ delete p;}
  19.      Y& operator =(Y y) // Y& operator=(const Y& y)  will be much better
  20.      {
  21.            *p = *y.p; // *p = *(y.p), not sure, might not needed, but add () already good code style
  22.            //return *this;
  23.      }
  24. private:
  25.     int* p;
  26. };
  27. void Delete(const X* x)  
  28. {
  29.     delete x; //can't delete const pointer
  30. }

  31. void Test()
  32. {
  33.     Y* y1 = new Y;
  34.     Y y2 = *y1;
  35.     Delete(y1);
  36. }
复制代码

评分

参与人数 1威望 +20 收起 理由
finger|regnif + 20 强!!!!!!!!

查看全部评分

回复  

使用道具 举报

5#
发表于 27-1-2012 13:58:20 | 只看该作者
老乞丐,这一句在Thinking in C++里说是可以这样做的

virtual int SomeFun() = 0{ return 1;}  //pure virtual function shouldn't contain implementation
回复  

使用道具 举报

6#
发表于 27-1-2012 13:58:58 | 只看该作者
这个100UL是个啥表示法阿??谁能帮俺解答一下?
回复  

使用道具 举报

7#
发表于 27-1-2012 14:54:45 | 只看该作者
原帖由 四香油饼 于 27-1-2012 13:58 发表
这个100UL是个啥表示法阿??谁能帮俺解答一下?
100 as unsigned long, 默认情况下100被解释为int
回复  

使用道具 举报

8#
发表于 27-1-2012 14:56:53 | 只看该作者
原帖由 四香油饼 于 27-1-2012 13:58 发表
老乞丐,这一句在Thinking in C++里说是可以这样做的

virtual int SomeFun() = 0{ return 1;}  //pure virtual function shouldn't contain implementation

you are right  

http://stackoverflow.com/questions/2089083/pure-virtual-function-with-implementation
回复  

使用道具 举报

9#
发表于 27-1-2012 15:59:08 | 只看该作者
原帖由 coredump 于 27-1-2012 15:54 发表
100 as unsigned long, 默认情况下100被解释为int


这个是属于C++标准里的么??在教材里从来没见过呢
回复  

使用道具 举报

10#
发表于 27-1-2012 16:06:06 | 只看该作者
原帖由 四香油饼 于 27-1-2012 15:59 发表


这个是属于C++标准里的么??在教材里从来没见过呢

是C的标准用法
http://www.cplusplus.com/doc/tutorial/constants/

评分

参与人数 1威望 +20 收起 理由
四香油饼 + 20 谢谢指点!

查看全部评分

回复  

使用道具 举报

11#
发表于 27-1-2012 22:26:25 | 只看该作者
class X                                                                               //有虚函数的类应该写虚析构函数
{
public:
    virtual int SomeFun() = 0{ return 1;}                      // 纯虚函数没有函数体
    void AnotherFun()const                                       
    {
         v = 100UL;                                                                    // const 不能修改成员
         printf("%d",v,v);                                                       // 应该只有1个参数v, %d是int,v是long,也有问题
    }
private:
    unsigned long v;
};
class Y : public X                                                            // 要override 父类的纯虚函数。 有动态内存分配的,应该写拷贝构造函数和override“=”
{
public:
    Y() : p( new int ){}               
     ~Y(){ delete p;}                                                           // 加上 p = NULL;
     Y& operator =(Y y)
     {
           *p = *y.p;                                                         //            if(NULL == p)  p = new int;            *p = *y.p;           return *this;
     }
private:
    int* p;
};
void Delete(const X* x)                       
{
    delete x;                                                               // 加上 x = NULL;
}

void Test()
{
    Y* y1 = new Y;
    Y y2 = *y1;
    Delete(y1);
}

很好的题目哦~~~  
估计还有没找出来的陷阱。

评分

参与人数 1威望 +20 收起 理由
coredump + 20 你太有才了!

查看全部评分

回复  

使用道具 举报

12#
 楼主| 发表于 27-1-2012 22:27:44 | 只看该作者
老乞丐你那个printf没有答对。。。

还有 pure virtual 可以有实现, 但这不过是小知识而已,没有什么太大实际意义。
回复  

使用道具 举报

13#
发表于 27-1-2012 23:08:59 | 只看该作者
先马克。。。回头来学习
回复  

使用道具 举报

14#
发表于 27-1-2012 23:09:32 | 只看该作者
能找出毛病来,能说明什么呢? 感觉像恶作剧
回复  

使用道具 举报

15#
发表于 27-1-2012 23:16:22 | 只看该作者
class X  必须有虚析构函数,否则 Delete(y1); 会调用~X(),不会调用~Y()。

详细说明如下(书上Copy来的):

// 基类与派生类的析构函数应该为虚,即加virtual 关键字例如
#include <iostream.h>
class Base
{
    public:
        virtual ~Base() { cout<< "~Base" << endl ; }
};

class Derived : public Base
{
    public:
        virtual ~Derived() { cout<< "~Derived" << endl ; }
};

void main(void)
{
    Base * pB = new Derived; // upcast
    delete pB;
}
输出结果为
~Derived
~Base
如果析构函数不为虚 那么输出结果为
~Base

另,coredump是在Brisbane Nokia工作吧? 看到coredump以前写的有关QT的帖子。。。


[ 本帖最后由 william_m76 于 28-1-2012 00:17 编辑 ]
回复  

使用道具 举报

16#
发表于 27-1-2012 23:55:24 | 只看该作者
我也来凑凑热闹。。

关于virtual的那个同意楼上,貌似在深入C++对象模型里面好像讲过,不过 记不清了。

printf那里面最好用%ld

我觉得最严重的一个问题是,没有定义copy constructor。注意Y y2 = *y1;这个用法,它会调用copy constructor,而不是那个重载的赋值操作符( 在本例中根本用不到它)。 因为copy constructor没有定义,那么编译器生成的那个就会做简单拷贝,就是把y1的p指针赋给个y2的p指针,两个对象的p指向相同的地方。最终可能导致crash。

评分

参与人数 2威望 +40 收起 理由
finger|regnif + 20 %ld 还是个warning
coredump + 20 我很赞同!

查看全部评分

回复  

使用道具 举报

17#
发表于 28-1-2012 00:11:18 | 只看该作者
原帖由 william_m76 于 27-1-2012 23:16 发表
class Derived : public Base
{
    public:
        virtual ~Derived() { cout<< "~Derived" << endl ; }
};

基类dtor为虚的话,派生类不必指定virtual关键字, 将会自动为virtual, 不过总是在virtual的方法上加上virtual是个好习惯
回复  

使用道具 举报

18#
发表于 28-1-2012 00:16:16 | 只看该作者
原帖由 dbsdsun 于 27-1-2012 23:09 发表
能找出毛病来,能说明什么呢? 感觉像恶作剧
这个例子不规范/错误的地方,的确太多, 而且有些是不应该鼓励去抓的语法陷阱/功能, 而有些是考察的C的语法.

记得哪位大牛说的来着, C++不管用了多久, 总有些你不知道的, 并且在知道了之后会大惊失色的地方, 上面那个油饼提醒我的就是, 从来不知道, 尽管都写了大半辈子的C++了.
回复  

使用道具 举报

19#
发表于 28-1-2012 00:17:03 | 只看该作者
原帖由 ciasom 于 27-1-2012 23:55 发表
printf那里面最好用%ld.

对, gcc的话, 应该最多给个warning, 不会是个error
回复  

使用道具 举报

20#
发表于 28-1-2012 00:25:09 | 只看该作者
原帖由 ciasom 于 27-1-2012 23:55 发表
没有定义copy constructor。注意Y y2 = *y1;这个用法,它会调用copy constructor,而不是那个重载的赋值操作符( 在本例中根本用不到它)。.

这点不同意, copy constructor应该是下面这样的代码才会被调用:

X x1;
X x2(x1);


这个例子中的 Y y2 = *y1;是个明确的赋值.  不过对于允许copy, 尤其是应该deep copy的情况下, 的确应该同时定义operator=和copy ctor. 从这方面说, 没有copy ctor的确算错误.
回复  

使用道具 举报

21#
 楼主| 发表于 28-1-2012 01:19:12 | 只看该作者
原帖由 coredump 于 27-1-2012 22:17 发表

对, gcc的话, 应该最多给个warning, 不会是个error


%ld 还是个warning
回复  

使用道具 举报

22#
 楼主| 发表于 28-1-2012 01:22:29 | 只看该作者
原帖由 coredump 于 27-1-2012 22:25 发表

这点不同意, copy constructor应该是下面这样的代码才会被调用:



这个例子中的 Y y2 = *y1;是个明确的赋值.  不过对于允许copy, 尤其是应该deep copy的情况下, 的确应该同时定义operator=和copy ctor. 从这方 ...


Y y2 = *y1 是copy ctor

[ 本帖最后由 finger|regnif 于 27-1-2012 23:26 编辑 ]
回复  

使用道具 举报

23#
 楼主| 发表于 28-1-2012 01:48:07 | 只看该作者
printf("%d",v,v); 一般 警告级别 开到最高, 以及视警告如错误 的人会知道.

VS我不是太确定, GCC肯定会有警告.

[ 本帖最后由 finger|regnif 于 27-1-2012 23:49 编辑 ]
回复  

使用道具 举报

24#
 楼主| 发表于 28-1-2012 01:56:41 | 只看该作者
原帖由 四香油饼 于 27-1-2012 11:58 发表
老乞丐,这一句在Thinking in C++里说是可以这样做的

virtual int SomeFun() = 0{ return 1;}  //pure virtual function shouldn't contain implementation


这个知道的人比较少. effectiveCpp3rd里也有讲到. 比较偏的东西了. 如果你show给面试官看的话可能会有点效果.

这个在本帖中属于可有可无的问题. 除此之外其它的错误应该是靠谱并实在的.

[ 本帖最后由 finger|regnif 于 27-1-2012 23:59 编辑 ]
回复  

使用道具 举报

25#
 楼主| 发表于 28-1-2012 02:03:21 | 只看该作者
原帖由 dbsdsun 于 27-1-2012 21:09 发表
能找出毛病来,能说明什么呢? 感觉像恶作剧


这个virtual int SomeFun() = 0{ return 1;}的确有点恶作剧. 其它的都很实在.

真正的恶作剧是这种: i++++i++i
回复  

使用道具 举报

26#
发表于 28-1-2012 02:35:59 | 只看该作者
原帖由 finger|regnif 于 28-1-2012 01:22 发表


Y y2 = *y1 是copy ctor

临睡觉前,特意验证了下
  1. #include

  2. using namespace std;


  3. class X
  4. {
  5. public:
  6.    X& operator=(const X& other)
  7.    {
  8.       cout << "operator= called";
  9.       return *this;
  10.    }
  11.    X() {}
  12.    X(const X& other) {
  13.       cout << "copy ctor called";
  14.    }
  15. };
  16. int main() {
  17.    X x1, x2;
  18.    x1 = x2; //output: operator= called
  19.   X x3(x1); //output:copy ctor called
  20.    return 0;
  21. }
复制代码
回复  

使用道具 举报

27#
发表于 28-1-2012 02:42:35 | 只看该作者
原帖由 finger|regnif 于 28-1-2012 02:03 发表


这个virtual int SomeFun() = 0{ return 1;}的确有点恶作剧. 其它的都很实在.

真正的恶作剧是这种: i++++i++i

后一种很孔乙己, 我如果面试人, 最标准的答案不是给出正确结果, 而是拒绝回答, 然后给出拒绝的理由就行.
用人做compiler的活, 不是自虐狂就是神经病, 谁写这样的代码, 被review的时候, 肯定被骂得狗血淋头
回复  

使用道具 举报

28#
 楼主| 发表于 28-1-2012 10:15:26 | 只看该作者
原帖由 coredump 于 28-1-2012 00:35 发表
......
X x1, x2;
x1 = x2; //output: operator= called



X x2;
X x1 = x2;


是不同的. 前一个是赋值, 后一个是copy ctor. 这也算是copy ctor和operator=要同时存在的其中一个原因.

实际开发中见过几个用 X x1=x2;然后只定义operator=不定义copy ctor, 然后出bug的. 所以做为一个茬放在这里.
回复  

使用道具 举报

29#
发表于 28-1-2012 10:17:05 | 只看该作者
原帖由 finger|regnif 于 28-1-2012 10:15 发表





是不同的. 前一个是赋值, 后一个是copy ctor. 这也算是copy ctor和operator=要同时存在的其中一个原因.

实际开发中见过几个用 X x1=x2;然后只定义operator=不定义copy ctor, 然后出bug的. 所以做为一 ...
对啦, 是我没仔细看,谢谢指出
回复  

使用道具 举报

30#
 楼主| 发表于 28-1-2012 10:34:08 | 只看该作者
原帖由 coredump 于 28-1-2012 00:42 发表

后一种很孔乙己, 我如果面试人, 最标准的答案不是给出正确结果, 而是拒绝回答, 然后给出拒绝的理由就行.
用人做compiler的活, 不是自虐狂就是神经病, 谁写这样的代码, 被review的时候, 肯定被骂得狗血淋头


刚毕业的时候还真做过 i++++i 这种题目. 我也认为 拒绝回答 是最好的答案. 其实对这种类似的语句, 很可能是未定义行为, 不同编译器实现不一样, 没有sequence point没有答案, .

评分

参与人数 1威望 +20 收起 理由
coredump + 20 我很赞同!

查看全部评分

回复  

使用道具 举报

您需要登录后才可以回帖 登录 | FreeOZ用户注册

本版积分规则

小黑屋|手机版|Archiver|FreeOZ论坛

GMT+10, 20-4-2024 11:36 , Processed in 0.055834 second(s), 53 queries , Gzip On, Redis On.

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表