1

Function1 可以使用任何类型 T 调用,该类型 T 将被转换为 (void*) 以便能够添加到列表中,但是这样我会丢失原始指针类型(我需要将 tham 存储在一个链表中,因为我不能为每个链表创建一个可能的类型)。所以不知何故我也需要保存指针的类型。我知道它不能使用 c++ 来完成。任何人都可以提出替代解决方案吗?

class MyClass
{

    template<class T>
    void function1(T* arg1)
    {
        myList.add((void*)arg);
    }

    void function2()
    {
        for(int i = 0; i < myList.size(); i++)
        {
            myList.get(i);
            //restore the original pointer type
        }
    }

    STLinkedlist<void*> myList;
}
4

5 回答 5

7

处理这类问题的常用方法是使用公共接口,在 C++ 中,这是通过继承完成的。这可能是一种拖累,尤其是在受约束的情况下,其中完整的类/接口层次结构会提供过多的代码/运行时开销。

Boost.Variant 进来了,它允许你使用同一个对象来存储不同的类型。如果您需要更多自由,请使用Boost.Any。如需比较,请参见此处的示例。

在一天结束的时候(或者更好:早晚),我会尝试以不同的方式做事,这样你就不会遇到这个问题。这最终可能是值得的。

于 2013-06-03T12:32:55.697 回答
6

如果你通过 void* 丢失了类型信息,它就消失了。你不能只是恢复它。

因此,您要么必须将额外信息与指针一起存储,然后使用分支代码将其转换回来,要么驱动设计以避免丢失。

你的情况很可疑,你没有做你真正想要的。

更常见的情况是您想要一个多态集合。那不存储任何类型的指针,而是那些属于同一层次结构的指针。Collection 具有 Base* 指针,您可以通过 Base 的接口使用对象,所有这些对象都可以调用适当的虚函数,而无需程序员交互。如果您真的需要转换为原始类型,您可以通过 dynamic_cast 安全地进行。或者在基本接口中添加一些类型信息支持。

于 2013-06-03T12:29:50.727 回答
3

Function1 可以使用任何类型 T 调用,该类型 T 将被转换为 (void*) 以便能够添加到列表中,但是这样我会丢失原始指针类型(我需要将 tham 存储在一个链表中,因为我不能为每个链表创建一个可能的类型)。

您遇到了 XY 问题。解决方案不是衰减指向 void* 的指针并存储类型信息。

您只需为每种可能的类型创建一个类型 - 您创建一个模板类型。您需要为您的“每个对象的类型”定义一个抽象接口,然后定义一个实现该接口的模板类,该接口按类型具体化。最后,您在收到的指针类型上创建自定义类型实例,并通过基类指针存储它们(其中基类是您的接口定义)。

综上所述,您(通常)根本不需要实现此功能,因为该功能已经在 boost::any 或 boost::variant 中实现(您必须选择其中之一)。

于 2013-06-03T12:41:35.620 回答
1

一般的

考虑到,如果您想在 中存储不同的对象std::vector<void *>,很可能您的应用程序设计不佳。在这种情况下,我想,是否真的有必要这样做(或者如何以另一种方式完成),而不是寻找解决方案,如何去做。

但是,C++(也没有任何其他语言)中没有完全邪恶的东西,所以如果你绝对确定这是唯一的解决方案,这里有三种可能的方法来解决你的问题。

选项1

如果只存储指向简单类型的指针,则将原始类型与指针一起存储为枚举值或简单的字符串。

enum DataType
{
    intType,
    floatType,
    doubleType
};

std::vector<std::pair<void *, DataType>> myData;

选项 2

如果您存储混合数据(类和简单类型),请将您的数据包装在某种类中。

class BaseData 
{ 
public:
    virtual ~BaseData() { }
};

class IntData : public BaseData
{
public:
    int myData;
};

std::vector<BaseData *> myData;

稍后,您将能够使用dynamic_cast.

选项 3

如果您只存储类,请将它们简单地存储为指向它们的基类和dynamic_cast您的出路的指针。

于 2013-06-03T12:22:13.997 回答
0

您可以使用boost::any将任何类型存储在列表中,而不是使用void*。这不是您想要的,但我认为您无法在运行时恢复类型(正如 Kerrek 所说,它不是 Java)。

class MyClass
{

   template<class T>
   void function1(T arg1)
   {
      myList.add(arg);
   }

   template<class T>
   T get(int i)
   {
      return boost::any_cast<T>(myList.get(i));
   }

   STLinkedlist<boost::any> myList;
};
于 2013-06-03T12:40:48.837 回答