C++ 使用static_cast处理混合(基本和派生)对象的向量是否存在性能风险?(又名“这是一个愚蠢的想法吗?”)
给定一个基类C++ 使用static_cast处理混合(基本和派生)对象的向量是否存在性能风险?(又名“这是一个愚蠢的想法吗?”),c++,vector,static-cast,C++,Vector,Static Cast,给定一个基类gameObject和一个派生类animatedGameObject,我认为最好将它们的所有实例存储在std::vector中。如果向量GameObjects被声明为gameObject*的基本类型,则派生对象实例需要强制转换 例如: vector<gameObject*> GameObjects; gameObject A* = new gameObject( ...init... ); animatedGameObject B* = new animatedGam
gameObject
和一个派生类animatedGameObject
,我认为最好将它们的所有实例存储在std::vector
中。如果向量GameObjects
被声明为gameObject*
的基本类型,则派生对象实例需要强制转换
例如:
vector<gameObject*> GameObjects;
gameObject A* = new gameObject( ...init... );
animatedGameObject B* = new animatedGameObject( ...init... );
GameObjects.push_back(A);
GameObjects.push_back(B);
// to access the animatedGameObject functions:
static_cast<animatedGameObject*>(GameObjects[1])->functionUniqueToAnimated();
矢量游戏对象;
游戏对象A*=新游戏对象(…初始化…);
animatedGameObject B*=新的animatedGameObject(…初始化…);
游戏对象。推回(A);
游戏对象。推回(B);
//要访问animatedGameObject函数,请执行以下操作:
静态_cast(GameObjects[1])->functionUniqueToAnimated();
我像往常一样害怕,我转向Scott Meyers(有效C++,第三版),他写的主题是:
许多程序员相信cast只会告诉编译器将一种类型视为另一种类型,但这是错误的。任何类型的类型转换(通过强制转换显式转换或由编译器隐式转换)通常都会导致在运行时执行代码
我已经阅读了他的第27条:最小化施法两次,但鉴于我在这方面的经验不足,我无法回答一个简单的问题“这是一件愚蠢的事情吗?”
我应该提到,有几个原因可以解释为什么这样做是愚蠢的,而与调用静态\u cast
无关。这些问题按重要性排列如下:
静态\u cast
可能存在的风险这是我第一次在这里问问题,所以如果有必要,请提前道歉。
static\u cast
不是适合这项工作的工具,除非您知道指针指向的是animatedGameObject
而不是游戏对象。您使用什么数据结构来存储这些信息
在基指针之后确定派生对象的类型是动态分派或dynamic\u cast
的工作。在您的示例中,调用GameObjects[1]->draw()
应该不使用强制转换,因为draw
应该是一个虚拟函数。否则,您可以使用dynamic\u cast(*GameObjects[1])
断言该对象是animatedGameObject,如果不是,则抛出std::bad\u cast
异常。(这仍然需要类游戏对象
中的虚拟
函数,通常是其析构函数。)
但是对多态派生类型执行静态\u cast
是一种代码味道
您还询问std::vector
是否是该用例的良好数据结构。它是,但不是“裸”指针的向量。C++11现在提供了“智能指针”内存管理类,这些类为您执行new
和delete
,使实际的操作符几乎过时。查看此案例的std::unique_ptr
若gameObjects[1]不是animatedGameObject,那个么应用程序(很可能)会可怕地死去
如果draw()是gameObject中存在的虚拟方法,则不需要进行转换
通常,将基类强制转换为派生类是不安全的。在这些情况下,使用动态_cast是有意义的。如果无法执行转换,则Dynamic_cast返回NULL
是否有比现有数据结构更好的数据结构
好吧,如果你的游戏对象没有在其他地方自动删除,那么使用类似于std::vector
的东西可能是有意义的。然而,标准共享指针可能会引入隐藏的开销(额外的new/delete,在最坏的情况下,如果它们被设计为线程安全的,它们甚至可能引入多线程互斥锁),因此,您应该确保这些开销与您的目标兼容。+1要阅读有效的C++,这里通常要做的事情是将draw()
定义为基类中的虚拟函数。然后,您可以简单地调用它,而不使用强制转换,这样做是正确的。你知道这一点,但想知道演员的具体效果吗?是的,我应该使用一个更好的函数名,对你评论末尾的问题回答是。你如何知道[1]
包含动画对象?我的意思是在你的代码的真实版本中。通常,这些信息可以被移动到程序结构中,或者被利用来更好地打包演员阵容,或者消除它。我将再次投票/提高可见性,使draw
虚拟化,这样就可以不用演员阵容了。这是虚拟函数基本上完美工作的经典例子之一。@jogojapan D'oh,我自己也弄糊涂了。自定义删除程序可以使唯一\u ptr
以多态方式处理非多态类型。我会修好的。非常感谢。去读一下std::shared_ptr
@ilya我犯了一个错误,std::unique_ptr
如果没有任何高级技术就可以了。我一直在想别的事情:让非多态类型以多态的方式行为。