识别已将哪个基类 shared_ptr 传递到超类 shared_ptr 向量中

Posted

技术标签:

【中文标题】识别已将哪个基类 shared_ptr 传递到超类 shared_ptr 向量中【英文标题】:Identifying which Base Class shared_ptr has been passed into a Super Class shared_ptr vector 【发布时间】:2012-12-02 19:27:55 【问题描述】:

我正在开发一个 C++ 项目,专门实现一个调车场算法。

我有一个函数可以创建一个超类shared_ptr 的向量,但是被推入这个向量的类都是基类shared_ptrs。

然后我需要获取这个向量并将其传递给另一个函数,并在 for 循环中对向量的每个元素执行不同的逻辑。然而,我执行的逻辑取决于向量的每个元素中存在哪个基类。

所以基本上我不知道的是如何识别向量的每个元素中的基类类型。当我调试它们时,它们都以类型超类的形式出现。

所以通常我想做这样的事情:

if(vectorElement == baseClass)

  //do some logic

或者,如果有一些我想念的不同方法来执行此操作,我会有兴趣执行此操作。

【问题讨论】:

我不能说我 100% 了解你,但你也许正在寻找 dynamic_castdynamic_pointer_cast 这两个术语基类和超类代表一个类派生自。派生类也称为子类(细微差别:-))。所以请编辑您的帖子以明确 可能有一种方法可以在我的解决方案中实现这一点,但我认为我能想到的任何方法都不可行。 我认为我确实需要使用 dynamic_pointer_cast,但我对其工作原理的理解并不清楚。如果有人能解释清楚,将不胜感激。 【参考方案1】:

您的问题有很多解决方案,坦率地说,这是 OOP 中几乎最常见的问题。

最明显的是虚函数在不同的类中做不同的事情:

class SuperClass 
public:
   virtual void doSomething(/*someArgsIfNeeded*/) 
      // some base implementation, possible empty
      // or just use pure virtual function here
   
;

class SubClass : public SuperClass 
public:
   virtual void doSomething(/*someArgsIfNeeded*/) 
      // some base implementation
   
;

然后按如下方式使用:

int SomeArgs;
std::vector<std::shared_ptr<SuperClass>> objects;
for (auto it = objects.begin(); it != objects.end(); ++i)
  it->doSomething(/*someArgsIfNeeded*/);

其他更复杂的解决方案是使用visitor pattern。


使用强制转换 (dynamic_cast) 被认为是一种不好的做法,因此始终寻找比强制转换更多的 OO 解决方案,就像我上面介绍的这两个。

【讨论】:

我不确定这个解决方案是否能解决我的问题。我知道我可以从向量中调用特定于基类的函数,但是我需要在不使用函数调用的情况下识别基类是哪个类。我实际上并没有从基类调用任何函数,也无法修改这些类。 @danner 澄清(提供代码或其他东西)这个描述“我有一个函数可以创建一个超类类型的 shared_ptr 向量,但是被推入这个向量的类都是基类 shared_ptrs . "... @danner 我的意思是哪些代码是你的,你可以修改,哪些不是你的,你不能修改......【参考方案2】:

在我的脑海中,一个简单的解决方案是在基类中有一个函数,它返回一个表示它是哪个类的 int。并且在每个派生类中,重写此函数以返回不同的值。您可以使用该值来确定将哪个类存储在向量中

编辑:通常类特定的细节将留在类中,这是多态性的重点。尝试将派生类特定的计算作为每个类中的覆盖成员函数进行,并使用它来获取值,而不需要在外部进行大型 for 循环(对于每个新的派生类)。

【讨论】:

通常做这样的自制类型 ID 是个坏主意。 dynamic_cast 就是针对这个问题发明的 是的,这行得通。我唯一的问题是我正在使用其他人的代码,并且我无法自己修改类。如果一切都失败了,我可以尝试这个解决方案,但是如果有一种方法可以在不修改首选类的情况下做到这一点。每个类中都有一个名为“is_convertable_from”的函数,它返回一个布尔值,具体取决于该类是否可以从基类转换。但我不完全确定它是如何工作的。 */#define DEF_IS_CONVERTABLE_FROM(type)\ public: virtual bool is_convertable_from( Token::pointer_type const& ptr ) const \ return dynamic_cast( ptr.get() ) != 0 ;\ 这就是那个函数。 . 所以事实证明我确实需要使用 static_dynamic_casting 来解决这个问题。使用 SDC,您可以将对象向下转换到层次结构的任何位置,并且仅当对象是层次结构的一部分时,转换才会起作用。因此,如果我将乘法对象转换为乘法对象,我可以使用 if 语句表示 If(multiplicationObject != 0) 或层次结构为 Operator->Multiplication 的运算符对象,我可以使用 if 语句表示 If(Operator != 0)。但是任何不属于层次结构的东西都会返回 0 或空,并且会在 if 中返回 false。

以上是关于识别已将哪个基类 shared_ptr 传递到超类 shared_ptr 向量中的主要内容,如果未能解决你的问题,请参考以下文章

将基类向量传递给接受超类向量的函数

未检测到超类中声明的 Swift 协议一致性

将协议添加到超类,这将强制从其继承的其他类实现协议

使用shared_ptr将基类引用值复制到映射

重构摘要11_处理概括关系

使用带有 boost::shared_ptr 的基类在地图中查找