如何验证指针指向的对象是否有效
相关代码
LookupTable<Product *> table;
Product temp = *table[selection];
// if *table[selection] is not a product, program crashes...
以下是Lookup表:
#ifndef LOOKUPTABLE_H
#define LOOKUPTABLE_H
#include <iostream>
#include <string>
using namespace std;
#define MAXRANGE 10
template <class T>
class LookupTable
{
private:
T *aptr[MAXRANGE];
int rangeStart[MAXRANGE];
int rangeEnd[MAXRANGE];
int numRanges;
public:
T defaultValue;
bool failedRangeCheck;
std::string failReason;
// Constructor
LookupTable()
{
numRanges = 0;
defaultValue = T();
}
void addRange(int start, int end)
{
std::cout << "Created a new range... Start: " << start << " / End: " << end << endl;
failedRangeCheck = false;
//lines omitted because not working anyway
if ( !failedRangeCheck )
{
//set ranges
rangeStart[numRanges] = start;
rangeEnd[numRanges] = end;
//build new generic array with end-start+1 positions
//set pointer to point to it
aptr[numRanges] = new T[ end - start + 1 ];
numRanges++;
}
else
{
std::cout << "Range overlapped another range." << endl;
std::cout << failReason << endl;
}
}
T &operator[](int value) // Overloaded [] operator
{
for ( int i = 0; i < numRanges; i++ )
{
if ( (value >= rangeStart[i]) && (value <= rangeEnd[i]) )
{
return aptr[i][value - rangeStart[i]];
}
}
return defaultValue;
}
~LookupTable()
{
delete[] aptr;
numRanges = 0;
}
};
#endif
答案 0 :(得分:3)
table
是LookupTable<Product*>
。为什么它包含不是Product*
的指针?这没有任何意义。
你不应该这样做。您需要执行此操作的唯一原因是:
通过一些错综复杂的演员,你在Product
中插入一个非table
的指针。对此的唯一解决方案是“不要那样做。”
你有一个指向Product
对象的指针,但你已经搞砸了你的对象生命周期管理,并在你完成之前销毁了对象。解决方案是使用范围限制资源管理(SBRM,也称为资源获取是初始化,或RAII),它允许自动管理生命周期。使用像shared_ptr
/ weak_ptr
这样的智能指针容器来实现此目的。
您将空指针放入table
。在这种情况下,您可以不将空指针放入查找表中,或者在从表中获取指针后检查指针是否为空。
答案 1 :(得分:1)
根据您在subsequent question中发布的LookupTable
代码,最终可以回答此问题。 (真的,我认为你应该把这些代码放在这里并删除另一个问题。)
table[selection]
要么返回对表中条目的引用(如果找到了选择),要么返回对默认初始化对象的引用。当LookupTable专门用于指针类型(例如代码中的Product*
)时,默认初始化对象将是NULL指针。
因此,对于代码中的LookupTable<Product*>
,表达式table[selection]
要么将结果指向表中找到的Product
,要么返回NULL Product
}指针。
因此,您应该实际获取指针值并检查它,而不是立即取消引用table[selection]
的结果并尝试将其分配给Product
对象。
这可以使用类似于:
的代码来完成Product* result = table[selection];
if(result != NULL)
{
Product temp = *result;
// do something with temp, etc, etc
}
else
{
cout << "invalid product code" << endl;
}
答案 2 :(得分:0)
您可以使用dynamic_cast
:
if (dynamic_cast<Product *>(table[selection])) != NULL)
{
...
}
但不要这样做。如果您发现自己需要根据对象的运行时类型采取特定操作,那么您几乎肯定会做错事。这就是虚函数的用途。
答案 3 :(得分:0)
听起来你需要dynamic_cast
。但你的设计听起来也很可疑。为什么您的收藏品不包含正确的类型?或者,如果您需要根据对象的类型做出决策,那么某种形式的多态性就是您最需要的。
答案 4 :(得分:0)
您可以使用RTTI。添加<typeinfo>
标题,然后说:
if (typeid(*table[selection]) == typeid(Product)) { ... }
但是这里的某些东西真的很可疑......上面的陈述基本上是同义反复的,你根本不应该这样做。 C ++是一种强类型语言,因此根据定义,Product
对象容器中包含的任何对象都是Product
的实例 - 除非你做了一些荒谬的事情,比如在容器中插入一个无效的对象使用reinterpret_cast
。
答案 5 :(得分:-2)
Product * temp = dynamic_cast<Product*>(table[selection]);
if (temp) {
do something
}
并且前进并做到这一点。人们会告诉你不要,但不要听他们。