C++ 什么是动态铸造的“好用”示例?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28080/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 12:20:20  来源:igfitidea点击:

What are some 'good use' examples of dynamic casting?

c++castingrttidynamic-cast

提问by OysterD

We often hear/read that one should avoid dynamic casting. I was wondering what would be 'good use' examples of it, according to you?

我们经常听到/读到应该避免动态转换。根据您的说法,我想知道它的“好用”示例是什么?

Edit:

编辑:

Yes, I'm aware of that other thread: it is indeed when reading one of the first answers there that I asked my question!

是的,我知道另一个线程:确实是在阅读那里的第一个答案时,我问了我的问题!

回答by Mark Ransom

This recent thread gives an example of where it comes in handy. There is a base Shape class and classes Circle and Rectangle derived from it. In testing for equality, it is obvious that a Circle cannot be equal to a Rectangle and it would be a disaster to try to compare them. While iterating through a collection of pointers to Shapes, dynamic_cast does double duty, telling you if the shapes are comparable and giving you the proper objects to do the comparison on.

最近的这个线程给出了一个它派上用场的例子。有一个基本的 Shape 类和从它派生的类 Circle 和 Rectangle 。在测试相等性时,很明显圆形不能等于矩形,尝试比较它们将是一场灾难。在遍历指向 Shapes 的指针集合时,dynamic_cast 有双重职责,告诉您这些形状是否具有可比性,并为您提供合适的对象来进行比较。

Vector iterator not dereferencable

向量迭代器不可解引用

回答by rlerallut

Here's something I do often, it's not pretty, but it's simple and useful.

这是我经常做的事情,它并不漂亮,但它简单而有用。

I often work with template containers that implement an interface, imagine something like

我经常使用实现接口的模板容器,想象一下

template<class T>
class MyVector : public ContainerInterface
...

Where ContainerInterface has basic useful stuff, but that's all. If I want a specific algorithm on vectors of integers without exposing my template implementation, it is useful to accept the interface objects and dynamic_cast it down to MyVector in the implementation. Example:

ContainerInterface 有基本有用的东西,但仅此而已。如果我想要一个关于整数向量的特定算法而不暴露我的模板实现,那么在实现中接受接口对象并 dynamic_cast 到 MyVector 是很有用的。例子:

// function prototype (public API, in the header file)
void ProcessVector( ContainerInterface& vecIfce );

// function implementation (private, in the .cpp file)
void ProcessVector( ContainerInterface& vecIfce)
{
    MyVector<int>& vecInt = dynamic_cast<MyVector<int> >(vecIfce); 
    // the cast throws bad_cast in case of error but you could use a
    // more complex method to choose which low-level implementation
    // to use, basically rolling by hand your own polymorphism.

    // Process a vector of integers
    ...
}

I could add a Process() method to the ContainerInterface that would be polymorphically resolved, it would be a nicer OOP method, but I sometimes prefer to do it this way. When you have simple containers, a lot of algorithms and you want to keep your implementation hidden, dynamic_cast offers an easy and ugly solution.

我可以向 ContainerInterface 添加一个 Process() 方法,该方法将被多态解析,这将是一个更好的 OOP 方法,但有时我更喜欢这样做。当你有简单的容器、很多算法并且你想隐藏你的实现时,dynamic_cast 提供了一个简单而丑陋的解决方案。

You could also look at double-dispatch techniques.

您还可以查看双分派技术。

HTH

HTH

回答by rlerallut

Well it would really be nice with extension methods in C#.

嗯,在 C# 中使用扩展方法真的很好。

For example let's say I have a list of objects and I want to get a list of all ids from them. I can step through them all and pull them out but I would like to segment out that code for reuse.

例如,假设我有一个对象列表,我想从中获取所有 id 的列表。我可以逐步完成并将它们拉出,但我想分割出该代码以供重用。

so something like

所以像

List<myObject> myObjectList = getMyObjects();

List<string> ids = myObjectList.PropertyList("id");

would be cool except on the extension method you won't know the type that is coming in.

除了在扩展方法上你不知道传入的类型之外会很酷。

So

所以

public static List<string> PropertyList(this object objList, string propName) {
    var genList = (objList.GetType())objList;
}

would be awesome.

会很棒。

回答by DrPizza

My current toy project uses dynamic_cast twice; once to work around the lack of multiple dispatch in C++ (it's a visitor-style system that could use multiple dispatch instead of the dynamic_casts), and once to special-case a specific subtype.

我当前的玩具项目使用了两次 dynamic_cast;一次是为了解决 C++ 中缺少多重分派的问题(它是一个访问者风格的系统,可以使用多重分派而不是 dynamic_casts),一次是为了对特定的子类型进行特殊处理。

Both of these are acceptable, in my view, though the former at least stems from a language deficit. I think this may be a common situation, in fact; most dynamic_casts (and a great many "design patterns" in general) are workarounds for specific language flaws rather than something that aim for.

在我看来,这两者都是可以接受的,尽管前者至少源于语言缺陷。事实上,我认为这可能是一种常见的情况;大多数 dynamic_casts(以及很多一般的“设计模式”)都是针对特定语言缺陷的解决方法,而不是针对某些目标。

回答by Eclipse

It can be used for a bit of run-time type-safety when exposing handles to objects though a C interface. Have all the exposed classes inherit from a common base class. When accepting a handle to a function, first cast to the base class, then dynamic cast to the class you're expecting. If they passed in a non-sensical handle, you'll get an exception when the run-time can't find the rtti. If they passed in a valid handle of the wrong type, you get a NULL pointer and can throw your own exception. If they passed in the correct pointer, you're good to go. This isn't fool-proof, but it is certainly better at catching mistaken calls to the libraries than a straight reinterpret cast from a handle, and waiting until some data gets mysteriously corrupted when you pass the wrong handle in.

当通过 C 接口向对象公开句柄时,它可以用于一些运行时类型安全。让所有公开的类都继承自一个公共基类。接受函数句柄时,首先转换为基类,然后动态转换为您期望的类。如果它们传入一个无意义的句柄,当运行时找不到 rtti 时,您将收到异常。如果他们传入了错误类型的有效句柄,您将获得一个 NULL 指针,并且可以抛出您自己的异常。如果他们传入了正确的指针,你就可以开始了。这不是万无一失的,但是在捕获对库的错误调用方面肯定比从句柄直接重新解释转换要好,并且等到某些数据在您传入错误句柄时被神秘损坏。

回答by Zsolt Szatmari

It is very useful, however, most of the times it is toouseful: if for getting the job done the easiest way is to do a dynamic_cast, it's more often than not a symptom of bad OO design, what in turn might lead to trouble in the future in unforeseen ways.

它非常有用,但是,大多数时候它有用了:如果要完成工作,最简单的方法是执行 dynamic_cast,这通常是糟糕的 OO 设计的症状,反过来可能会导致麻烦在未来以不可预见的方式。