良好的设计可以完全避免演员阵容吗?

时间:2011-12-11 22:59:32

标签: c++ oop casting code-design

我想知道是否存在完全需要铸造的情况 我在这里谈论类之间的转换,而不是基本类型。

是一种代码气味的铸造(无论是像static_castdynamic_cast这样的C ++风格,还是普通的C风格演员)?我可以看到它有时候会有所帮助,但我认为它也可以避免。是否会破坏任何OOP规则?

4 个答案:

答案 0 :(得分:3)

不是特别的。应尽可能避免强制转换,但在最基本的层面上,C ++区域存在于类型安全领域之外,并且必须使用强制转换。 dynamic_cast是一个特殊的例外,具体来说,即使在坚固的OOP设计中,也可以

有“那是不完美的”,而且有“OMGWTF,Y U SO DUMB”。演员阵容不完美。

答案 1 :(得分:2)

如果通过代码嗅觉你的意思是它应该在代码审查中提出一个标志,那么它们就是代码味道。如果你的意思是它们永远不会出现在代码中,那么不,有一些很好用的演员表。

对于一个有趣的示例(我总是发现类型擦除有趣),请查看boost::any的实现,其中需要dynamic_cast才能安全地读取存储的值(与union不同,你必须猜测类型并且是有限的)

草图:

struct any_base {
   virtual ~any_base() {}
};
template <typename T>
struct any_data : any_base {
   T value;
   any_data( T const & value ) : value(value) {}
};
struct any {
   any_base * data;
   any() : data() {}
   ~any() { delete data; }

   template <typename T>
   any( T const & v ) : data( new any_data<T>(v) {}
}
template <typename T>
T any_cast( any const & a ) {
   any_base<T> * p = dynamic_cast< any_base<T>* >( a.data );
   if ( !p ) throw invalid_cast();
   return *p;
}

答案 2 :(得分:0)

典型的例子是I / O:这是投射的少数和唯一的原因之一,它也使用C ++中唯一合法的指针类型之一:char *

uint32_t n;
infile.read(reinterpret_cast<char *>(&n), sizeof n);
n *= 2;
outfile.write(reinterpret_cast<const char *>)(&n), sizeof n);

其他“类I / O”操作需要类似的模式,例如加密或编码转换。

(在分配的上下文中使用时,C ++中的另一个合法指针是void *,但它不需要强制转换:将内存指针“转换”为对象的C ++方法指针是通过构造void * addr = get_memory();,然后是T * p = new (addr) T;。)

答案 3 :(得分:0)

我认为良好的设计不能完全避免铸造,因为有合理的情况下铸造是一个不错的选择。代理非常有用,通常依赖于隐式或显式转换,例如下面的延迟评估。

template <class fn_t, class result_t>
class lazy_t {
    fn_t fn_;
public:

    lazy_t(fn_t fn) : fn_ (fn) { }

    operator result_t () { return fn_(); }
};

在这种情况下,编译器可以使用隐式转换来执行给定函数的延迟评估。我认为转换运算符是类的公共接口的一部分。

的dynamic_cast&LT;&GT;在某些情况下也是必要的,例如实施多次发送。有关详情,请参阅http://en.wikipedia.org/wiki/Multiple_dispatch

有时您的程序需要复杂的代码。你不能总是坚持语言的简单,基本或“干净”的元素。