Массив указателей на абстрактный класс: на nullptr или не на nullptr (C ++) - PullRequest
0 голосов
/ 23 сентября 2019

Я хочу перебрать массив указателей на абстрактный класс, чтобы найти «пустой» слот, то есть проверить, указывает ли элемент на объект производного класса или нет.Мой подход заключается в создании массива и установке каждого элемента на nullptr.Затем я могу проверить, является ли элемент nullptr.

Это работает, но есть ли лучший способ?Редактировать: Могу ли я проверить первый «пустой» элемент в массиве указателей на абстрактный класс (в котором производные классы будут периодически создаваться и указываться массивом, делая этот элемент не «пустым»), не назначая каждый элементк nullptr при настройке массива и последующей проверке на nullptr как способ проверить, является ли элемент «пустым»?Другими словами, могу ли я напрямую проверить, указывает ли элемент на построенный базовый класс или нет?

Cat** catArray = new Cat*[200];
for(int i = 0; i < 200; i++){
   catArray[i] = nullptr;
}

for(int i = 0; i < 200; i++){
   if(catArray[i] == nullptr){ //edited, was typo as "!="
      AddRealCat(...);
      break;
   }
}      

Интересно, есть ли более простой способ сделать это, чтобы проверить, есть ли элемент в массиве указателей?на абстрактный класс указывает на объект производного класса или является просто абстрактным указателем, не устанавливая для элемента значение nullptr.Например, есть ли bool IsObject (ObjectType * ptr) или что-то в стандартной библиотеке?

И мне интересно, если установка каждого элемента на nullptr создает какие-либо потенциальные проблемы, кроме вычисленийстоимость обхода массива и установки элементов в nullptr.

Ответы [ 2 ]

0 голосов
/ 23 сентября 2019

Я думаю, что действительно более простой способ сделать это, используя dynamic_cast, использует std::vector вместо необработанного указателя.

Пример кода

#include <string>
#include <iostream>
#include <vector>

struct Cat{
    virtual ~Cat() = default;
    virtual void meow() const = 0;
};

struct Meow : Cat{
    void meow() const override{ std::cout << "meow" << std::endl; }
};

int main()
{
    std::vector<Cat*> vec{100}; // you don't need to nullptr initilize your vector
    vec[1] = new Meow();

    for(auto c : vec){
        if(auto m = dynamic_cast<Meow*>(c)){
            m->meow();
        }
    }

    // don't forget to release memory
    for(auto c : vec){
        delete c;
    }
}

Живой пример

Современная версия с использованием интеллектуальных указателей.

#include <string>
#include <iostream>
#include <vector>
#include <memory>

struct Cat{
    virtual ~Cat() = default;
    virtual void meow() const = 0;
};
struct Meow : Cat{
    void meow() const override{ std::cout << "meow" << std::endl; }
};

int main()
{
    std::vector<std::unique_ptr<Cat>> vec{100};
    vec[1] = std::make_unique<Meow>();

    for(auto&& c : vec){
        if(auto m = dynamic_cast<Meow*>(c.get())){
            m->meow();
        }
    }

    // you don't need to manually clear the memory.
}

Живой пример

0 голосов
/ 23 сентября 2019

Вы должны будете использовать dynamic_cast , чтобы привести указатель базового класса к указателю производного класса.dynamic_cast выполняет безопасное приведение типов вниз.

Если результат dynamic_cast не равен nullptr, преобразование выполнено успешно.В противном случае указатель производного класса не может быть получен из указателя.

Вы должны сделать это следующим образом:

Cat *pCat = dynamic_cast<Cat*>(catArray[i]);
if (pCat)
{
    AddRealCat(...);
    break;
}

, где catArray - массив указателей базового класса.

Обновление

Я думаю, что есть ошибка при создании массива реальных объектов cat:

for(int i = 0; i < 200; i++){
   if(catArray[i] != nullptr){
      AddRealCat(...);
      break;
   }
}

Конечно, вам нужно проверить == nullptr поскольку вы инициализируете все элементы массива в nullptr?Я думаю, вам нужно внести следующие изменения:

for(int i = 0; i < 200; i++){
   if(catArray[i] == nullptr){
      catArray[i] = new RealCat();
      break;
   }
}    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...