JuggernautDad
JuggernautDad

Reputation: 1145

c++ pointers to objects type checking

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

Answers (6)

TheUndeadFish
TheUndeadFish

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

Charles Salvia
Charles Salvia

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

James McNellis
James McNellis

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

Colin
Colin

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

Brian Agnew
Brian Agnew

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

Oliver Charlesworth
Oliver Charlesworth

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

Related Questions