c++指向对象类型检查的指针
如何验证指针指向的对象是否有效
相关代码
LookupTable<Product *> table;
Product temp = *table[selection];
// if *table[selection] is not a product, program crashes...
以下是查找表:
#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
How do I verify that an object being pointed by a pointer is valid
relevant code
LookupTable<Product *> table;
Product temp = *table[selection];
// if *table[selection] is not a product, program crashes...
Here is what Lookup table is:
#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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
table
是一个LookupTable
。为什么它会包含一个不是Product*
的指针?这没有任何意义。你不应该需要这样做。您需要执行此操作的唯一原因是:
通过一些复杂的转换,您将一个指向非
Product
的指针插入到table
中。唯一的解决方案是“不要这样做。”您有一个指向
Product
对象的指针,但是您搞砸了对象生命周期管理,并且在使用完该对象之前就销毁了该对象。解决方案是使用范围限制资源管理(SBRM,也称为资源获取初始化,或 RAII),它允许自动管理生命周期。使用像shared_ptr
/weak_ptr
这样的智能指针容器来实现这一点。您将一个空指针放入
表
中。在这种情况下,您可以不将空指针放入查找表中,或者在从表中获取指针后检查指针是否为空。table
is aLookupTable<Product*>
. Why would it contain a pointer that isn't aProduct*
? That doesn't make any sense.You shouldn't ever need to do this. The only reasons you would need to do this are if:
Through some convoluted cast you inserted a pointer to something that isn't a
Product
intotable
. The only solution to this is "don't do that."You have a pointer to what was a
Product
object, but you've screwed up your object lifetime management and you destroyed the object before you were done with it. The solution to this is to use scope-bound resource management (SBRM, also called Resource Acquisition is Initialization, or RAII), which allows lifetimes to be automatically managed. Use a smart pointer container likeshared_ptr
/weak_ptr
to facilitate this.You put a null pointer into the
table
. In this case, you can either just not put null pointers into the lookup table, or check whether a pointer is null after you obtain it from the table.基于您在后续问题中发布的
LookupTable
代码,这个问题终于可以回答了。 (真的,我认为您应该将该代码放在这里并删除其他问题。)table[selection]
要么返回对表中条目的引用(如果找到选择),要么返回对默认初始化对象的引用。当 LookupTable 专门用于指针类型(例如代码中的Product*
)时,默认初始化的对象将是 NULL 指针。因此,对于代码中的
LookupTable
,表达式table[selection]
要么将结果放入指向Product
的指针中code> 在表中找到,或者是 NULLProduct
指针。因此,您实际上应该获取指针值并检查它,而不是立即取消引用
table[selection]
的结果并尝试将其分配给Product
对象。这可以通过类似于以下的代码来完成:
Based on the code of
LookupTable
that you posted in a subsequent question, this question can finally be answered. (Really, I think you ought to just put that code here and remove the other question.)table[selection]
either returns a reference to an entry in the table (if the selection is found) or otherwise a reference to a default-initialized object. When LookupTable is specialized for a pointer type (such as theProduct*
in your code) then the default-initialized object will be a NULL pointer.So, for the
LookupTable<Product*>
in your code, the expressiontable[selection]
is either going the result in a pointer to aProduct
found within the table or else a NULLProduct
pointer.Consequently, instead of immediately dereferencing the result of
table[selection]
and trying to assign it to aProduct
object, you should actually take the pointer value and examine it.This would be accomplished with code similar to:
您可以使用
dynamic_cast
:但是不要这样做。如果您发现自己需要根据对象的运行时类型采取特定操作,那么您几乎肯定做错了什么。这就是虚拟函数的用途。
You can use
dynamic_cast
:But DON'T DO THIS. If you find yourself needing to take specific action based on the runtime type of an object, you're almost certainly doing something wrong. This is what virtual functions are for.
听起来您需要
dynamic_cast
。但你的设计听起来也很可疑。为什么您的集合不包含正确的类型?或者,如果您需要根据对象的类型做出决定,那么您最可能需要某种形式的多态性。It sounds like you need
dynamic_cast
. But your design also sounds suspect. Why would your collection not contain the right types ? Or, if you need to make decisions based upon the type of your object, then some form of polymorphism is what you'd most likely require.您可以使用 RTTI。包含
标头,并说:但是这里有些东西确实可疑...上面的语句基本上是同义反复,您不需要这样做根本不。 C++ 是一种强类型语言,因此根据定义,包含在
Product
对象容器中的任何对象都是Product
的实例 - 除非您做了一些荒谬的事情,例如插入使用reinterpret_cast
将无效对象放入容器中。You can use RTTI. Include the
<typeinfo>
header, and say:But something is really fishy here... the above statement is basically tautological, and you shouldn't need to do this at all. C++ is a strongly typed language, and so any object contained in a container of
Product
objects is, by definition, an instance ofProduct
- unless you did something ridiculous, like inserting an invalid object into the container using areinterpret_cast
.并继续执行此操作。人们会告诉你不要这样做,但不要听他们的。
and GO AHEAD AND DO THIS. People will tell you not to, but don't listen to them.