c ++ указатели на проверку типов объектов - PullRequest
0 голосов
/ 04 ноября 2010

Как проверить, что объект, на который указывает указатель, действителен

соответствующий код

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

Ответы [ 6 ]

3 голосов
/ 04 ноября 2010

table является LookupTable<Product*>.Почему он содержит указатель, который не является Product*?Это не имеет никакого смысла.

Вам никогда не нужно это делать.Единственные причины, по которым вам нужно это сделать, это:

  • Через какое-то запутанное приведение вы вставили указатель на что-то, что не является Product в table.Единственное решение этого - «не делай этого».

  • У вас есть указатель на то, что было Product объектом, но вы испортили управление временем жизни вашего объекта иВы уничтожили объект до того, как закончили с ним.Решением этой проблемы является использование управления ресурсами с привязкой к области (SBRM, также называемое Resource Acquisition is Initialization, или RAII), которое позволяет автоматически управлять временем жизни.Для этого используйте контейнер интеллектуальных указателей, например shared_ptr / weak_ptr.

  • Вы положили нулевой указатель в table.В этом случае вы можете просто не указывать нулевые указатели в таблице поиска или проверить, является ли указатель нулевым после получения его из таблицы.

1 голос
/ 04 ноября 2010

Исходя из кода 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;
}
0 голосов
/ 04 ноября 2010

Вы можете использовать RTTI. Включите заголовок <typeinfo> и скажите:

if (typeid(*table[selection]) == typeid(Product)) { ... }

Но что-то здесь действительно подозрительно ... вышеприведенное утверждение в основном тавтологично, и вам вообще не нужно этого делать. C ++ является строго типизированным языком, и поэтому любой объект, содержащийся в контейнере Product объектов, по определению является экземпляром Product - если вы не сделали что-то смешное, например, вставили недействительный объект в контейнер с помощью reinterpret_cast.

0 голосов
/ 04 ноября 2010
Product * temp = dynamic_cast<Product*>(table[selection]);
if (temp) {
   do something
}

и вперед и сделай это. Люди скажут вам не делать этого, но не слушайте их.

0 голосов
/ 04 ноября 2010

Похоже, вам нужно dynamic_cast. Но ваш дизайн также звучит подозрительно. Почему ваша коллекция не содержит правильных типов? Или, если вам нужно принимать решения, основываясь на типе вашего объекта, вам скорее всего понадобится некая форма полиморфизма.

0 голосов
/ 04 ноября 2010

Вы можете использовать dynamic_cast:

if (dynamic_cast<Product *>(table[selection])) != NULL)
{
    ...
}

Но НЕ ДЕЛАЙТЕ ЭТОГО . Если вы обнаружите, что вам нужно предпринять определенные действия в зависимости от типа объекта во время выполнения, вы почти наверняка делаете что-то не так. Для этого и нужны виртуальные функции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...