获得Void * C ++的价值

时间:2014-09-09 12:20:21

标签: c++ void-pointers

我有一个void指针,我想获得指针所指的内容。

void class :: method(void * pointer)
{
     cout<<pointer; // The address which the pointer refers to.
     cout<<?; //The content of where the pointer refers to.
}  

pointer的原始类型未知。

编辑:目标是允许创建一个“泛型方法”,它获取任何类型的参数,并为每个参数执行相同的操作。 限制是该方法是虚拟的,因此我不能使用模板方法。

2 个答案:

答案 0 :(得分:2)

您需要将void*强制转换回其原始类型(即在转换为void*之前)。然后你可以取消引用指针并使用它指向的内容。

EG。 :

void fun(void* ptr) {
    int* iptr = (int*) ptr;
    std::cout << *iptr;
}

int* iptr = new int(42);
fun(iptr);

以适合您特定用例的方式执行此操作的一种方法是使用类似boost::any的泛型类型传递对象的类型信息:

#include <iostream>
#include <string>
#include <boost/any.hpp>

class Foo {
    public :
    virtual void fun(const boost::any& obj) {
        if (typeid(int) == obj.type()) {
            std::cout << boost::any_cast<int>(obj) << std::endl;
        }
        else if (typeid(std::string) == obj.type()) {
            std::cout << boost::any_cast<std::string>(obj) << std::endl;
        }
        else {
            std::cout << "unsupported type" << std::endl;
        }
    }
};

int main(void) {
    Foo foo;
    int i = 42;
    std::string s = "str";
    float f = 1.1f;
    foo.fun(i);
    foo.fun(s);
    foo.fun(f);
    return 0;   
}

但这可能会非常冗长,具体取决于您希望支持多少种类型。

答案 1 :(得分:1)

这是不可能的。 C ++中的类型(主要)是编译时属性。在运行时,类型是未知的(它们是erased)

但是,RTTI存在,特别是对于包含虚拟方法的某些class的实例。

一般来说,没有可能的伎俩。您可以通过使用某种variant type 来重新设计您的程序,或者通过使用所有您的对象继承的公共根类等等,或者使用union types(最好有自己的受歧视的联盟)。

换句话说:当编译器看到void*指针时,它甚至不知道该指针所指向的数据的大小。

未来的C ++标准可能会提出一些std::any容器。

也许你可以拥有像

这样廉价的歧视联盟类
class Int_or_String {
   const bool isint;
   union {
     int n;
     std::string s;
   };
   Int_or_String(const int i) : isint(true), n(i) {};
   Int_or_String(const std::string &st): isint(false), s(st) {};
   ~Int_or_String() { if (isint) n=0; else 
     /*not sure*/ s.std::string::~std::string(); };
   // much more is missing
};

我甚至不确定显式销毁union成员的语法。

参见例如明确调用析构函数的this question

也许Qt object model可能会激励你。另请参阅其QVariant

通常的方法是在程序中定义一个根类并采用约定,所有对象都继承这个根类(或者甚至所有有意义的数据都在从该根目录派生的对象中)类)。这需要重新设计整个事物。

所以你会决定你的根类是

class Root {
public:
  virtual void out(std::ostream&s) =0;
  virtual ~Root() =0;
  /// other common methods
};

static inline std::ostream& operator << (std::ostream&o, const Root &r)
   { r.out(o); return o; }


class Integer : public Root {
   const int num;
 public:
   Integer(int n) : Root(), num(n) {};
   void out (std::ostream &o) { o << num ; }; 
   /// etc...
 }; // end class Num


class String : public Root {
   const std::string str;
 public:
   String(const std::string& s) : Root(), str(s) {};
   void out (std::ostream &o) { o << str ; }; 
   /// etc...
 }; // end class String