安全地检查变量的类型 [英] Safely checking the type of a variable

查看:147
本文介绍了安全地检查变量的类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于一个系统,我需要将一个指针转换为long,然后长回指针类型。你可以猜到这是非常不安全的。我想做的是使用dynamic_cast进行转换,所以如果我混合他们我会得到一个空指针。此页面上显示 http://publib.boulder.ibm.com/infocenter/lnxpcomp/v7v91/index.jsp?topic=/com.ibm.vacpp7l.doc/language/ref/clrc05keyword_dynamic_cast.htm

For a system I need to convert a pointer to a long then the long back to the pointer type. As you can guess this is very unsafe. What I wanted to do is use dynamic_cast to do the conversion so if I mixed them I'll get a null pointer. This page says http://publib.boulder.ibm.com/infocenter/lnxpcomp/v7v91/index.jsp?topic=/com.ibm.vacpp7l.doc/language/ref/clrc05keyword_dynamic_cast.htm


dynamic_cast运算符在运行时执行
类型转换。
dynamic_cast操作符保证
将指向基本的指针的转换
类转换为指向派生类的指针
或转换lvalue
指向基类到一个派生类的
引用。 A
程序可以安全地使用类
层次。此运算符和
typeid运算符在
C ++中提供运行时
类型信息(RTTI)支持。

The dynamic_cast operator performs type conversions at run time. The dynamic_cast operator guarantees the conversion of a pointer to a base class to a pointer to a derived class, or the conversion of an lvalue referring to a base class to a reference to a derived class. A program can thereby use a class hierarchy safely. This operator and the typeid operator provide run-time type information (RTTI) support in C++.

我想得到一个错误,如果它是null所以我写了我自己的动态转换

and I'd like to get an error if it's null so I wrote my own dynamic cast

template<class T, class T2> T mydynamic_cast(T2 p)
{
	assert(dynamic_cast<T>(p));
	return reinterpret_cast<T>(p);
}



使用MSVC我得到错误error C2681:'long' dynamic_cast类型。事实证明,这将只适用于具有虚拟功能的类... WTF!我知道动态转换的点是上/下铸造继承问题,但我也认为这是动态解决类型转换问题。我知道我可以使用reinterpret_cast,但这不能保证同样的安全类型。

With MSVC I get the error "error C2681: 'long' : invalid expression type for dynamic_cast". It turns out this will only work with classes which have virtual functions... WTF! I know the point of a dynamic cast was for the up/down casting inheritance problem but I also thought it was to solve the type cast problem dynamically. I know I could use reinterpret_cast but that doesn't guarantee the same type of safety.

我应该使用什么来检查我的类型转换是否是相同的类型?我可以比较两个typeid,但我会有一个问题,当我想类型转换到它的基地。

What should I use to check if my typecast are the same type? I could compare the two typeid but I would have a problem when I want to typecast a derived to its base. So how can I solve this?

推荐答案

在用语言编写的应用程序中加载C ++ DLL时,我不得不做类似的事情只支持C接口。这是一个解决方案,如果传入意外的对象类型,会立即产生错误。这可以使事情出错时更容易诊断。

I've had to do similar things when loading C++ DLLs in apps written in languages that only support a C interface. Here is a solution that will give you an immediate error if an unexpected object type was passed in. This can make things much easier to diagnose when something goes wrong.

是你作为句柄传递的每个类都必须从公共基类继承。

The trick is that every class that you pass out as a handle has to inherit from a common base class.

#include <stdexcept>
#include <typeinfo>
#include <string>
#include <iostream>
using namespace std;


// Any class that needs to be passed out as a handle must inherit from this class.
// Use virtual inheritance if needed in multiple inheritance situations.
class Base
{

public:
    virtual ~Base() {} // Ensure a v-table exists for RTTI/dynamic_cast to work
};


class ClassA : public Base
{

};

class ClassB : public Base
{

};

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

// Convert a pointer to a long handle.  Always use this function
// to pass handles to outside code.  It ensures that T does derive
// from Base, and that things work properly in a multiple inheritance
// situation.
template <typename T>
long pointer_to_handle_cast(T ptr)
{
    return reinterpret_cast<long>(static_cast<Base*>(ptr));
}

// Convert a long handle back to a pointer.  This makes sure at
// compile time that T does derive from Base.  Throws an exception
// if handle is NULL, or a pointer to a non-rtti object, or a pointer
// to a class not convertable to T.
template <typename T>
T safe_handle_cast(long handle)
{
    if (handle == NULL)
    	throw invalid_argument(string("Error casting null pointer to ") + (typeid(T).name()));

    Base *base = static_cast<T>(NULL); // Check at compile time that T converts to a Base *
    base = reinterpret_cast<Base *>(handle);
    T result = NULL;

    try
    {
    	result = dynamic_cast<T>(base);
    }
    catch(__non_rtti_object &)
    {
    	throw invalid_argument(string("Error casting non-rtti object to ") + (typeid(T).name()));
    }

    if (!result)
    	throw invalid_argument(string("Error casting pointer to ") + typeid(*base).name() + " to " + (typeid(T).name()));

    return result;
}

int main()
{
    ClassA *a = new ClassA();
    ClassB *b = new ClassB();
    ClassC *c = new ClassC();
    long d = 0; 


    long ahandle = pointer_to_handle_cast(a);
    long bhandle = pointer_to_handle_cast(b);
    // long chandle = pointer_to_handle_cast(c); //Won't compile
    long chandle = reinterpret_cast<long>(c);
    // long dhandle = pointer_to_handle_cast(&d); Won't compile
    long dhandle = reinterpret_cast<long>(&d);

    // send handle to library
    //...
    // get handle back
    try
    {
    	a = safe_handle_cast<ClassA *>(ahandle);
    	//a = safe_handle_cast<ClassA *>(bhandle); // fails at runtime
    	//a = safe_handle_cast<ClassA *>(chandle); // fails at runtime
    	//a = safe_handle_cast<ClassA *>(dhandle); // fails at runtime
    	//a = safe_handle_cast<ClassA *>(NULL); // fails at runtime
    	//c = safe_handle_cast<ClassC *>(chandle); // Won't compile
    }
    catch (invalid_argument &ex)
    {
    	cout << ex.what() << endl;
    }

    return 0;
}

这篇关于安全地检查变量的类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆