2010-07-05 88 views
1

与生产中存在的代码类似。你们能否回顾一下,告诉我这些代码是否能够一直运作良好?评论此C++代码

class Base 
{ 
    public: 
     virtual void process() = 0; 
}; 

class ProductA : public Base 
{ 
    public: 
    void process() 
    { 
     // some implementation. 
     doSomething(); 
    } 

    void setSomething(int x) 
    { 

    } 

    virtual void doSomething() 
    { 
     // doSomething. 
    } 

}; 

class ProductANew : public ProductA 
{ 
    public: 
     ProductANew() : ProductA() { } 
     void doSomething() 
     { 
      // do Something. 
     } 
}; 


int main(int argc, char *argv[]) 
{ 
    Base* bp = new ProductANew(); 
    dynamic_cast<ProductA*>(bp)->setSomething(10); 
    bp->process(); 
} 
+3

我猜'class ProductA'的定义实际上应该从'class ProductA:public Base'开始。 – 2010-07-05 10:13:12

+1

您的担心是什么 - 动态转换?这些来自/为什么不能使用ProductA *而不是Base * - 您是否将ProductA存储在通用阵列或类似的数据中? – Rup 2010-07-05 10:13:43

+0

那里有一个具体的问题,就像dynamic_cast的这种使用总是工作等等?对于记录,如果RTTI不适合,dynamic_cast可能会给你一个空指针,而你不需要检查就直接解引用。但是,如果这实际上是你的生产代码,并且在这种实例化之后立即执行转换,那么你没有什么可担心的。哦,而且您的ProductA不会从Base继承... – falstro 2010-07-05 10:14:16

回答

7

有了好的设计,你不会需要一个dynamic_cast。如果process()不能在未致电setSomething()的情况下调用,则应该将它们暴露在相同的基类中。

+0

是的..这是我期待的评论评论之一。谢谢。 – Jagannath 2010-07-05 10:21:14

+0

一个很好的设计是什么?是 - 只是一个疯狂的猜测 - Base的子类将封装算法的实现,然后这些对象将被安排为一个进程的网络?如果是这样的话,在基本接口上暴露doSomething()的尖锐建议对我来说不是一个好主意... – miquelramirez 2010-07-05 12:23:01

+0

@miquelramirez,如果setSomething(int x)是什么基本方法的一部分,并提供了一个默认的实现?我们不需要一个dynamic_cast产品的权利。 – Jagannath 2010-07-05 14:21:56

19

一些问题:

  • 基类必须有一个虚析构函数
  • 你永远不删除的对象的新
  • 分配你从来没有测试的dynamic_cast的结果
1

通常你会发现那些甚至无法编译的代码是非常糟糕的设计。

Base* bp = new ProductANew(); 

此行不能工作,因为ProductANew不以任何方式,形状或形式从Base继承。

$ gcc junk.cc 
junk.cc: In function ‘int main(int, char**)’: 
junk.cc:41: error: cannot convert ‘ProductANew*’ to ‘Base*’ in initialization 

(只要是明确的:junk.cc包含你的代码剪切并粘贴)


编辑补充...

迟到者可能想看看投票前原始问题的历史。 ;)

+4

-1'删除'按钮可以用来删除虚假答案,这样人们的时间不会花费在阅读它们。 – 2010-07-05 11:02:35

3

有一个实际的错误和一堆危险/问题的做法:


的一个错误是,你永远叫deletenew版的对象,所以它泄漏。


问题的做法:

  1. Base没有虚析构函数,因此,如果您通过调用delete或使用auto_ptr纠正错误,你会调用未定义的行为。
  2. 根本没有必要使用动态分配。
  3. 多态基类应该是不可复制的,以防止对象切片。
  4. 您在使用dynamic_cast而不需要检查结果 - 为什么不只是声明bp作为指向ProductANewProductNew的指针呢?
  5. ProductANew不需要一个构造函数 - 默认的就可以了。

其中几点可能是你的例子的性质的结果 - 即你有充分的理由使用动态分配,但你想保持你的例子小。

+0

IIRC,在大多数平台上,应用程序的堆在终止时会自动释放。因此,绝对不推荐删除'delete',但本身不是错误,并且不一定会导致泄漏。 – Mac 2010-07-06 04:01:59

+0

我仍然认为任何在程序结束时没有被销毁的对象都是错误的 - 但是你是对的,在任何现代的消费者环境中,这不是一个问题,除非对象拥有一些其他的操作系统资源无法为你清理。 – 2010-07-06 07:23:01