为啥向下转换在 C++ 中是一种不好的做法,而不是在另一种语言中呢? [关闭]

Posted

技术标签:

【中文标题】为啥向下转换在 C++ 中是一种不好的做法,而不是在另一种语言中呢? [关闭]【英文标题】:Why would down casting be a bad practice in C++ and not in another language? [closed]为什么向下转换在 C++ 中是一种不好的做法,而不是在另一种语言中呢? [关闭] 【发布时间】:2015-06-08 08:39:40 【问题描述】:

我曾经问过一个关于如何设计一段 C++ 代码的问题(可以在这里找到 C++ - Good or bad practice?),人们告诉我,向下转换被认为是一种不好的做法,除非是非常特殊的场景。

但是,我已经看到 C# 和 Java 中的许多代码片段,这似乎是一种完全自然的做事方式。例如,在 android SDK 中,您有函数 Activity#findViewById() 返回一个视图,然后您将其向下转换为它的实际类:

TextView tv = (TextView) this.findViewById( R.id.myTextView );

为什么在 C++ 中而不是在其他语言中需要避免这种情况? 我知道 C# 和 Java 都支持本机自省,而不是 C++ 需要类型字段,但最终它是同一件事,不是吗?

【问题讨论】:

为什么一些随机的仇恨者想要结束这个完全合法的问题? 是什么让您认为在其他语言中向下转换是可以的?这个问题似乎是从一个不受支持的前提开始的。 @chi:我知道 OP 来自哪里。确实,我看到人们一直在警告不要在 C++ 中向下转换,但在其他语言中却很少。 @chi 我假设创建 android 的人不是初学者并且知道什么是好的或坏的做法,并从他们设计 API 的方式推断出它在 Java 中是合法的。 @Virus721 你怎么能说向下转换不是java中的床练习​​?如果您说的是正确的,那么为什么 java 具有通用框架....(我只从您在问题中提到的“另一种语言”中了解 java) 【参考方案1】:

至少有几个非常不同的原因,所有这些都很重要:

    概念:其他语言(尤其是 Java,但在很大程度上也包括 C# 和强烈鼓励使用“引用类型”的类似语言)使用运行时多态性作为单一的解决许多不同问题的工具(编译时多态性、代码重用、性能增强、类型擦除、运行时多态性等),而 C++ 对个别问题有不同、更专业和更合适的解决方案。 (模板、值类型等可用于解决个别问题。)因此,C++ 中的多态性在其他语言中不太常见,在其他常见的情况下,通常(但不总是)不适合使用等效的向下转换或instanceof

    实用:与其他运算符的性能相比,C++ 中的向下转换运算符基本上非常慢,主要是因为 C++ 允许多个- 和虚拟继承。其他语言没有,所以他们的演员表要简单得多。此外,某些编译器的实现自身历来具有更慢的向下转换实现(例如,我相信 64 位 Visual C++ 就是其中之一)。因此,除了概念上的原因(#1)之外,由于其实际性能特征,开发人员不惜一切代价试图避免它。

由于这些原因,除非绝对需要,否则在 C++ 中使用 dynamic_cast 确实是个坏主意。

【讨论】:

使用static_cast 向下转换并不是“非常慢”。 感谢您的回答。不过我不明白这部分:polymorphism in C++ is much less common in other languages。你是说,在 C++ 中,多态性应该比在其他语言中更频繁地使用? @T.C.: ...我知道你知道我说的是dynamic_cast而不是static_cast。 -__- @Virus721:我说的正好相反——它应该less经常使用,因为C++对于许多问题有更好的解决方案,而其他语言没有更好的解决方案为。【参考方案2】:

在 C++ 中使用相同的习惯用法,其中 API 接受一个处理程序并将 void*long 传递给它,或者将此类变量与 API 对象的实例一起存储。在WINAPI中,RegisterClass是前者的典型例子,Set/GetWindowLongPtr是后者的典型例子。这些是您提到的“非常具体的场景”,它适用于托管语言和 C++。

通常,静态类型语言避免向下转换,因为它将类型检查从编译转移到运行时。

【讨论】:

【参考方案3】:

在其他解释器语言中,类型检查是在 JVM 等解释器中完成的。在 C++ 中,您必须手动进行类型检查。

【讨论】:

AFAIK dynamic_cast() 执行类型检查,如果目标类型无效则抛出异常。 另外,JVM 不是解释器。

以上是关于为啥向下转换在 C++ 中是一种不好的做法,而不是在另一种语言中呢? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

为啥直接从 Servlet 访问 DAO 是一种不好的做法?

为啥使用“评估”是一种不好的做法?

从后台线程更新 UI 是一种不好的做法,为啥? [关闭]

为啥单身人士被认为是一种不好的做法? [复制]

使用 js 渲染 html 是一种不好的做法吗? [关闭]

使用动态是不是被认为是一种不好的做法?