类似于下面编写的代码存在于生产中。你们有人可以审查它并告诉我这些代码是否一直运行良好。
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();
}
答案 0 :(得分:19)
一些问题:
答案 1 :(得分:7)
设计良好,您不需要dynamic_cast
。如果在未调用process()
的情况下无法调用setSomething()
,则它们应该已在同一基类中公开。
答案 2 :(得分:3)
有一个实际错误和一堆危险/可疑的做法:
一个错误是您永远不会在delete
ed对象上调用new
,因此它会泄漏。
可疑行为:
Base
没有虚拟析构函数,因此如果您通过调用delete
或使用auto_ptr
来更正错误,则会调用未定义的行为。dynamic_cast
,但并未检查结果 - 为什么不将bp
声明为ProductANew
或ProductNew
的指针?ProductANew
不需要构造函数 - 默认构造函数也可以。这些点中的一些可能是您的示例性质的结果 - 即您有充分的理由使用动态分配,但您希望保持您的示例小。
答案 3 :(得分: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包含你的代码剪切和粘贴。)
已编辑添加...
迟到者可能希望在投票前查看原始问题的历史。 ;)