Reputation: 1145
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
Upvotes: 0
Views: 2074
Reputation: 8171
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 the Product*
in your code) then the default-initialized object will be a NULL pointer.
So, for the LookupTable<Product*>
in your code, the expression table[selection]
is either going the result in a pointer to a Product
found within the table or else a NULL Product
pointer.
Consequently, instead of immediately dereferencing the result of table[selection]
and trying to assign it to a Product
object, you should actually take the pointer value and examine it.
This would be accomplished with code similar to:
Product* result = table[selection];
if(result != NULL)
{
Product temp = *result;
// do something with temp, etc, etc
}
else
{
cout << "invalid product code" << endl;
}
Upvotes: 1
Reputation: 53289
You can use RTTI. Include the <typeinfo>
header, and say:
if (typeid(*table[selection]) == typeid(Product)) { ... }
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 of Product
- unless you did something ridiculous, like inserting an invalid object into the container using a reinterpret_cast
.
Upvotes: 0
Reputation: 355039
table
is a LookupTable<Product*>
. Why would it contain a pointer that isn't a Product*
? 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
into table
. 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 like shared_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.
Upvotes: 3
Reputation: 3752
Product * temp = dynamic_cast<Product*>(table[selection]);
if (temp) {
do something
}
and GO AHEAD AND DO THIS. People will tell you not to, but don't listen to them.
Upvotes: -2
Reputation: 272247
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.
Upvotes: 0
Reputation: 272467
You can use dynamic_cast
:
if (dynamic_cast<Product *>(table[selection])) != NULL)
{
...
}
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.
Upvotes: 0