finger|regnif 发表于 26-1-2012 03:38:46

C++找茬,找出代码中存在的问题

那试试找出代码的问题,给出你理由。
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);
}

四香油饼 发表于 26-1-2012 15:53:02

我怎么觉得到处都是问题阿,首先就是看不懂:( ,怎么SomeFun后面都没用到过,定义这个纯虚函数有什么意义阿?

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

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

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

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

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

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

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

finger|regnif 发表于 27-1-2012 01:53:34

原帖由 四香油饼 于 26-1-2012 12:53 发表 http://freeoz.org/ibbs/images/common/back.gif
我怎么觉得到处都是问题阿,首先就是看不懂:( ,怎么SomeFun后面都没用到过,定义这个纯虚函数有什么意义阿?

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

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

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

coredump 发表于 27-1-2012 14:32:19

class X
{
public:
    //an additional virtual ~X() {} needed here
    virtual int SomeFun() = 0{ return 1;}//pure virtual function shouldn't contain implementation
    void AnotherFun()const
    {
         v = 100UL; //can't change member value in const method
         printf("%d",v,v); //2 v with 1 '%d'
    }
private:
    unsigned long v;
};
class Y : public X
{
public:
    Y() : p( new int ){}//p(new int(0))
   ~Y(){ delete p;}
   Y& operator =(Y y) // Y& operator=(const Y& y)will be much better
   {
         *p = *y.p; // *p = *(y.p), not sure, might not needed, but add () already good code style
         //return *this;
   }
private:
    int* p;
};
void Delete(const X* x)
{
    delete x; //can't delete const pointer
}

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

四香油饼 发表于 27-1-2012 14:58:20

老乞丐,这一句在Thinking in C++里说是可以这样做的

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

四香油饼 发表于 27-1-2012 14:58:58

这个100UL是个啥表示法阿??谁能帮俺解答一下?

coredump 发表于 27-1-2012 15:54:45

原帖由 四香油饼 于 27-1-2012 13:58 发表 http://www.freeoz.org/ibbs/images/common/back.gif
这个100UL是个啥表示法阿??谁能帮俺解答一下? 100 as unsigned long, 默认情况下100被解释为int

coredump 发表于 27-1-2012 15:56:53

原帖由 四香油饼 于 27-1-2012 13:58 发表 http://www.freeoz.org/ibbs/images/common/back.gif
老乞丐,这一句在Thinking in C++里说是可以这样做的

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

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

四香油饼 发表于 27-1-2012 16:59:08

原帖由 coredump 于 27-1-2012 15:54 发表 http://www.freeoz.org/ibbs/images/common/back.gif
100 as unsigned long, 默认情况下100被解释为int

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

coredump 发表于 27-1-2012 17:06:06

原帖由 四香油饼 于 27-1-2012 15:59 发表 http://www.freeoz.org/ibbs/images/common/back.gif


这个是属于C++标准里的么??在教材里从来没见过呢
是C的标准用法
http://www.cplusplus.com/doc/tutorial/constants/

tonychangcheng 发表于 27-1-2012 23: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);
}

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

finger|regnif 发表于 27-1-2012 23:27:44

老乞丐你那个printf没有答对。。。

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

MillerYang 发表于 28-1-2012 00:08:59

先马克。。。回头来学习

dbsdsun 发表于 28-1-2012 00:09:32

能找出毛病来,能说明什么呢? 感觉像恶作剧

william_m76 发表于 28-1-2012 00: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 编辑 ]

ciasom 发表于 28-1-2012 00:55:24

我也来凑凑热闹。。

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

printf那里面最好用%ld

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

coredump 发表于 28-1-2012 01:11:18

原帖由 william_m76 于 27-1-2012 23:16 发表 http://www.freeoz.org/ibbs/images/common/back.gif
class Derived : public Base
{
    public:
      virtual ~Derived() { cout<< "~Derived" << endl ; }
};
基类dtor为虚的话,派生类不必指定virtual关键字, 将会自动为virtual, 不过总是在virtual的方法上加上virtual是个好习惯

coredump 发表于 28-1-2012 01:16:16

原帖由 dbsdsun 于 27-1-2012 23:09 发表 http://www.freeoz.org/ibbs/images/common/back.gif
能找出毛病来,能说明什么呢? 感觉像恶作剧 这个例子不规范/错误的地方,的确太多, 而且有些是不应该鼓励去抓的语法陷阱/功能, 而有些是考察的C的语法.

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

coredump 发表于 28-1-2012 01:17:03

原帖由 ciasom 于 27-1-2012 23:55 发表 http://www.freeoz.org/ibbs/images/common/back.gif
printf那里面最好用%ld.
对, gcc的话, 应该最多给个warning, 不会是个error

coredump 发表于 28-1-2012 01:25:09

原帖由 ciasom 于 27-1-2012 23:55 发表 http://www.freeoz.org/ibbs/images/common/back.gif
没有定义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的确算错误.

finger|regnif 发表于 28-1-2012 02:19:12

原帖由 coredump 于 27-1-2012 22:17 发表 http://freeoz.org/ibbs/images/common/back.gif

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

%ld 还是个warning

finger|regnif 发表于 28-1-2012 02:22:29

原帖由 coredump 于 27-1-2012 22:25 发表 http://freeoz.org/ibbs/images/common/back.gif

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



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

Y y2 = *y1 是copy ctor

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

finger|regnif 发表于 28-1-2012 02:48:07

printf("%d",v,v); 一般 警告级别 开到最高, 以及视警告如错误 的人会知道.

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

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

finger|regnif 发表于 28-1-2012 02:56:41

原帖由 四香油饼 于 27-1-2012 11:58 发表 http://freeoz.org/ibbs/images/common/back.gif
老乞丐,这一句在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 编辑 ]

finger|regnif 发表于 28-1-2012 03:03:21

原帖由 dbsdsun 于 27-1-2012 21:09 发表 http://freeoz.org/ibbs/images/common/back.gif
能找出毛病来,能说明什么呢? 感觉像恶作剧

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

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

coredump 发表于 28-1-2012 03:35:59

原帖由 finger|regnif 于 28-1-2012 01:22 发表 http://www.freeoz.org/ibbs/images/common/back.gif


Y y2 = *y1 是copy ctor
临睡觉前,特意验证了下#include

using namespace std;


class X
{
public:
   X& operator=(const X& other)
   {
      cout << "operator= called";
      return *this;
   }
   X() {}
   X(const X& other) {
      cout << "copy ctor called";
   }
};
int main() {
   X x1, x2;
   x1 = x2; //output: operator= called
X x3(x1); //output:copy ctor called
   return 0;
}

coredump 发表于 28-1-2012 03:42:35

原帖由 finger|regnif 于 28-1-2012 02:03 发表 http://www.freeoz.org/ibbs/images/common/back.gif


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

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

finger|regnif 发表于 28-1-2012 11:15:26

原帖由 coredump 于 28-1-2012 00:35 发表 http://freeoz.org/ibbs/images/common/back.gif
......
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的. 所以做为一个茬放在这里.

coredump 发表于 28-1-2012 11:17:05

原帖由 finger|regnif 于 28-1-2012 10:15 发表 http://www.freeoz.org/ibbs/images/common/back.gif





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

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

finger|regnif 发表于 28-1-2012 11:34:08

原帖由 coredump 于 28-1-2012 00:42 发表 http://freeoz.org/ibbs/images/common/back.gif

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

刚毕业的时候还真做过 i++++i 这种题目. 我也认为 拒绝回答 是最好的答案. 其实对这种类似的语句, 很可能是未定义行为, 不同编译器实现不一样, 没有sequence point没有答案, .
页: [1] 2
查看完整版本: C++找茬,找出代码中存在的问题