好吧,我正在使用Map存储任何类型的指针(void *),并且它正在范围对象中使用。这是范围类。
class Scope
{
protected:
Scope * parent;
MyMap* map;
public:
virtual void setParent(Scope* p)=0;
virtual Scope* getParent()=0;
virtual void setOwner(void * owner)=0;
virtual void * getOwner()=0;
virtual Symbol * get(char* name)=0;
virtual Symbol * get(char* name, Signature * sig)=0;
MyMap* getMap()const;
};
并且有两个类OrderedScope
和DisorderedScope
来实现Scope
类。
在我的项目中,我试图将所有数据存储为void *,然后检索它们并将它们转换为适当的类型。当我在其类型上转换对象时,我发现有些数据丢失了。这是我得到的照片。
只是为了澄清Package
类有Scope。在该范围内,我存储Function
类型的对象。所以当我想向它添加一个函数时,我应该首先检索包对象,然后我可以使用add
函数来插入新函数。
我不知道我是否正确地展示了这个问题,但我希望如此。 感谢您的帮助。
答案 0 :(得分:2)
Void指针是一种危险的机制,因为它们禁用了编译器对该指针的类型检查。因此,如果您犯了一个错误(例如将void指针转换为错误的类型),您将不会收到编译时错误,您只会注意到该问题是运行时错误行为,例如数据损坏。
所以,回答这个问题:如果你想使用void指针并避免数据损坏,你必须非常肯定当你将一个void-pointer转换为(SomeType *)时,内存位置为void -pointer指向实际上包含有效(SomeType *)而没有其他内容。特别是,您必须确保void指针指向的(SomeType *)仍然有效,并且在创建void-pointer和尝试强制转换的时间之间没有被删除/释放。用它。您还需要了解combining void pointers with multiple inheritance时涉及的潜在问题,因为具有多个超类的类可以根据您正在查看的超类来使用不同的“this”指针,并且转换为void指针赢得为你自动存储正确的“this”指针(因为编译器不知道你以后会对哪个“this”指针感兴趣)。
这一切都是可行的,但在所有情况下,你的程序逻辑必须100%正确。除了非常仔细地编码所有内容,研究寻找错误的代码并对其进行彻底测试之外,没有其它方法。像valgrind和Purify这样的代码检查程序也可以通过运行代码来查找症状并不总是很明显的错误。
那就是说,上面的评论者是对的 - 通常使用void指针更好/更安全。这些替代方案(例如模板和/或公共基类)更不容易出错,因为它们让编译器在编译时为您检测错误,而不是强迫您在运行时逐个搜索它们。另外,考虑使用智能指针(例如shared_ptr)而不是原始指针,因为这会将处理对象的生命周期卸载到编译器,编译器可以比手动编码更可靠,更一致地处理该任务。