C ++ приведение указателя на указатели (x **) -> (y **)

0

Я новичок в C++, и я решил провести эксперименты с указателями на указатели. Я пытаюсь создать систему, в которой я могу использовать и абстрактный класс, чтобы определить интерфейс, который многие не связанные между собой классы могут наследовать (часто через множественное наследование), чтобы затем я мог перетащить их на некоторые общие вспомогательные функции.

Я закипил код до такой степени, насколько могу, поэтому извиняюсь, если листинг немного длинный...

//------------ HEADER

struct IClassData
{
    virtual int Width() = 0;
    virtual int Height() = 0;
};

class ClassA
{
    public:
        ClassA(int w, int h);

        protected:
            int _Width;
            int _Height;
};


class Derived : public ClassA, public IClassData
{
    public:
        Derived();
        Derived(int w, int h);

    virtual int Width() override;
    virtual int Height() override;
};

class Computron
{
public:
    static int TotalWidth(IClassData** data, int size)
    {
        int curSum = 0;
        for (int i = 0; i < size; i++)
        {
            curSum += data[i]->Width();
        }

        return curSum;
    }
};

// -------------- CPP
ClassA::ClassA(int w, int h)
{
    _Width= w;
    _Height = h;
}

Derived::Derived() : ClassA(0,0) { /* NONE */ } 
Derived::Derived(int w, int h) : ClassA(w,h) { /* NONE */ } 

int Derived::Width() { return _Width; }
int Derived::Height() { return _Height; }

Поэтому в моей основной программе я создаю несколько экземпляров производного класса, и я хочу сделать кастинг таким образом, чтобы он мог работать против таких функций:

// --------------- MAIN

...
const int MAX = 5;
    Derived** data = new Derived*[MAX];

    for (int i = 0; i < MAX; i++)
    {
        data[i] = new Derived(i, i*2);
    }

    // Cast an compute
    int size = Computron::TotalWidth((IClassData**)data, MAX);
...

Поэтому мои большие вопросы:
1. Это нормально, или я буду стрелять в ногу позже? Я понимаю, что мои занятия здесь очень простые, но если они будут очень сложными, это вызовет некоторые проблемы на линии?
2. Кроме того, есть ли вероятность, что подобный прилив может не работать во время выполнения по какой-то причине?
3. Мне лучше использовать шаблон для этих типов сценариев?

  • 0
    " Это нормально, или я буду стрелять себе в ногу позже?" Что конкретно? Можете ли вы подробнее рассказать о конкретных сомнениях в вашем дизайне или хотя бы дать краткий пример кода, воспроизводящего ваши проблемы?
  • 0
    Если у вас нет действительно веских причин, вы не должны использовать чистые интерфейсы. Вы знаете, у нас есть шаблоны?
Показать ещё 2 комментария
Теги:
pointers
casting

1 ответ

0

Это нормально, или я буду стрелять в ногу позже? Я понимаю, что мои занятия здесь очень простые, но если они будут очень сложными, это вызовет некоторые проблемы на линии?

Я ничего здесь не вижу, что вообще кричит о проблемах, но я настоятельно рекомендую использовать стандартную библиотеку, чтобы избежать проблем с управлением памятью позже. Например, вместо вашего массива я бы использовал:

std::vector<std::unique_ptr<Derived>> data;

Когда data выходят за рамки, вектор будет уничтожен. Это, в свою очередь, приведет к уничтожению unique_ptr и автоматически удалит Derived объекты.

Однако вам нужны только указатели, в которых вам нужно быть полиморфными и хранить разные типы объектов в одном массиве; то есть, скорее всего, вам это понадобится, если вы храните указатели на объекты IClassData, где вы точно не знаете, какой производный тип будет отображаться в массиве во время выполнения. Как написано, вы можете просто использовать std::vector<Derived> потому что знаете, что все объекты будут Derived экземплярами.

Кроме того, есть ли вероятность того, что подобный прилив может не работать во время выполнения по какой-то причине?

Не используйте C-style cast в C++. Вы должны использовать static_cast здесь, и он даже не работает во время компиляции, поскольку он нарушает систему типов.

Derived ** a = new Derived*[MAX];
Base ** b = static_cast<Base **>(a); // This line will not compile, because...

b[0] = new Base();           // Now a[0] is a Base rather than a Derived??
a[0]->some_derived_method(); // What should happen!?!?

Мне лучше просто использовать шаблон для этих типов сценариев?

Каждый сценарий отличается, поэтому ответ является окончательным "возможно".

  • 0
    Обратите внимание, что unique_ptr требует C ++ 11 или более поздней unique_ptr . В более ранних версиях был только auto_ptr , который небезопасно использовать в контейнерах STL (одна из причин, по которой был создан unique_ptr для замены auto_ptr ).
  • 0
    Спасибо, но я не ищу совет по управлению памятью. Да, если бы у меня был единственный случай, когда я использовал только производные, я бы это сделал. Я спрашиваю о нескольких неизвестных типах, которые могут использовать IClassData и поэтому могут быть отправлены в упомянутую служебную функцию.
Показать ещё 5 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню