C ++: проблемы с наследованием и списком функций как членов класса - PullRequest
0 голосов
/ 13 июня 2018

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

На мойпроблема, у меня есть родительский, частично виртуальный класс, определенный следующим образом:

class ModeInformation {


public:
    ModeInformation() { m_CreateModes(); m_CreateModeChoiceList(); } // These two functions are always called when an object belonging to the ModeInformation parent class is created, as they store elements in two lists, one in which the pointer-to-Modes themselves are stored, the other where Menu options are stored according to the number of modes
    virtual ~ModeInformation() {}

// Modes of a Weapon (virtual as they might be overridden in child classes)
    virtual Mode* pMode1() const { return NULL; }
    virtual Mode* pMode2() const { return NULL; }
    virtual Mode* pMode3() const { return NULL; }
    virtual Mode* pMode4() const { return NULL; }
    virtual Mode* pMode5() const { return NULL; }

// Lists mentioned earlier 
    virtual list<string>* ModeChoiceList() const { return new list<string>; }
    virtual list<Mode*>* Modes() const { return new list<Mode*>; };

// m_CreateModes() stores pointers-to-Mode in Modes(), if these are not NULL
    void m_CreateModes() {
        if (!pMode1() == NULL) { Modes()->push_back(pMode1()); }
        if (!pMode2() == NULL) { Modes()->push_back(pMode2()); }
        if (!pMode3() == NULL) { Modes()->push_back(pMode3()); }
        if (!pMode4() == NULL) { Modes()->push_back(pMode4()); }
        if (!pMode5() == NULL) { Modes()->push_back(pMode5()); }
    }

// m_CreateModeChoiceList() stores strings in ModeChoiceList(), composed using the sstring library. Also a source of problems, as I will point out later on.
    void m_CreateModeChoiceList() {
        int i = 1;
        for (list<Mode*>::iterator it = Modes()->begin(); it != Modes()->end(); it++) {
            stringstream ChoiceDeclaration;
            ChoiceDeclaration << "\n" << i << ".- Mode " << i;
            ModeChoiceList()->push_back(ChoiceDeclaration.str());
            i++;
        }
        ModeChoiceList()->push_back("\n0.- Quit to previous menu.");
    }

// m_PrintBasicInfo() is called from classes that possess an object pertaining to the ModeInformation class (or derived child-classes), serves as a decision tree to judge whether the Mode List should be printed (in the case the Weapon being printed possesses more than one Mode), otherwise it will print the very first Mode
    void m_PrintBasicInfo() {
        if (Modes()->size() > 1) {
            m_PrintModeList();
            m_ChooseModeFromList();
        }
        else {
            pMode1()->m_PrintBasicInfo(1);
        }
    }

// m_PrintModeList() prints each of the elements stored in ModeChoiceList()
    void m_PrintModeList() {
        list<string>::iterator it = ModeChoiceList()->begin();
        while (it != ModeChoiceList()->end()) {
            cout << *it << endl;
            it++;
        }
    }

// m_ChooseModeFromList() provides a dynamic method for a user to choose which Mode's information will be printed
    virtual void m_ChooseModeFromList() {
        int Input = 0;
        cout << "Please input your choice." << endl;
        cin >> Input;
        cout << endl;
        list<Mode*>::iterator it = Modes()->begin();
        switch (Input) {
        case 1: if (it != Modes()->end()) { (*it)->m_PrintBasicInfo(Input); it++; break; }
                else { m_ChooseInvalidModeFromList(); break; }
        case 2: if (it != Modes()->end()) { (*it)->m_PrintBasicInfo(Input); it++; break; }
                else { m_ChooseInvalidModeFromList(); break; }
        case 3: if (it != Modes()->end()) { (*it)->m_PrintBasicInfo(Input); it++; break; }
                else { m_ChooseInvalidModeFromList(); break; }
        case 4: if (it != Modes()->end()) { (*it)->m_PrintBasicInfo(Input); it++; break; }
                else { m_ChooseInvalidModeFromList(); break; }
        case 5: if (it != Modes()->end()) { (*it)->m_PrintBasicInfo(Input); it++; break; }
                else { m_ChooseInvalidModeFromList(); break; }
        case 0: cout << "Returning to previous menu..." << endl; break;
        default: m_ChooseInvalidModeFromList(); break;
        }
    }

// m_ChooseInvalidModeFromList() prints an invalid option message, and returns to m_ChooseModeFromList()
    void m_ChooseInvalidModeFromList() {
        cout << "Invalid option. Please choose a valid mode." << endl;
        m_ChooseModeFromList();
    }
};

У меня также есть пример дочернего класса, принадлежащего к Оружию, который я использую для проверки жизнеспособности и выполнения кода.Это как описано ниже:

class RailGunModeInformation : public ModeInformation {
public:
    Mode* pMode1() const { return new RailGunMode1(); }
    Mode* pMode2() const { return new RailGunMode2(); }
    list<string>* ModeChoiceList() const { return new list<string>; }
    list<Mode*>* Modes() const { return new list<Mode*>; }
};

В данный момент он компилируется, но я продолжаю получать «Необработанное исключение в 0x0FC3CAB6 (ucrtbased.dll) в Factory Method.exe: недопустимый параметр был передан функциикоторый считает неверные параметры фатальными. "ошибка.Независимо от того, сколько я пытаюсь переделать это, сохраняя при этом его общую функцию, я не могу заставить его работать, получая массу различных ошибок.Поэтому я решил обратиться к экспертам за помощью, поскольку часами бился головой о стену, пытаясь преодолеть это препятствие.

1 Ответ

0 голосов
/ 13 июня 2018

Ваша первая проблема заключается в следующем:

void m_CreateModes() {
    if (!pMode1() == NULL) { Modes()->push_back(pMode1()); }
    if (!pMode2() == NULL) { Modes()->push_back(pMode2()); }
    if (!pMode3() == NULL) { Modes()->push_back(pMode3()); }
    if (!pMode4() == NULL) { Modes()->push_back(pMode4()); }
    if (!pMode5() == NULL) { Modes()->push_back(pMode5()); }
}

Как уже упоминалось в комментариях, Modes () каждый раз возвращает новый список, но результат из puch_back недоступен после следующего '}'

Я просто буду использовать C ++ 11 для удаления некоторых более утомительных аспектов кода.

using ModeList = list<Mode*>;

ModeList m_CreateModes() {
    ModeList modes = Modes();
    if (!pMode1() == NULL) { modes->push_back(pMode1()); }
    if (!pMode2() == NULL) { modes->push_back(pMode2()); }
    if (!pMode3() == NULL) { modes->push_back(pMode3()); }
    if (!pMode4() == NULL) { modes->push_back(pMode4()); }
    if (!pMode5() == NULL) { modes->push_back(pMode5()); }
    return modes;
}

Теперь режимы работают до выхода из функции и возвращаются, вызывающая сторона должна теперь сохранять возвращенныезначение или информация потеряна.В качестве альтернативы, если вы хотите использовать значения, возвращаемые режимы могут быть переменной-членом базового класса.

Другие проблемы, это может быть неправильно понято

    if (!pMode1() == NULL) { modes->push_back(pMode1()); }

Допустим, pMode1 () возвращает NULL, тогда вы получаете, и NULL определяется как (0)

    if (!NULL == NULL) { Modes()->push_back(pMode1()); }

    if (true == 0) { Modes()->push_back(pMode1()); }

, и если он возвращает что-то не NULL

    if (!0xdeadbeef == NULL) { Modes()->push_back(pMode1()); }

    if (false == 0) { Modes()->push_back(pMode1()); }

Итак, что вы действительно хотели, замените NULL на nullptr (C++ 11)

    if (!pMode1() == nullptr ) { modes->push_back(pMode1()); }

Теперь вы получаете предупреждение о том, что bool не является nullptr_t, и вы должны написать

    if (!(pMode1() == nullptr) ) { modes->push_back(pMode1()); }

или

    if (pMode1() != nullptr ) { modes->push_back(pMode1()); }

или даже

    if (pMode1()) { modes->push_back(pMode1()); }

Другие примечания

m_ChooseModeFromList, вероятно, пропускает цикл.

многократное использование одного и того же кода с разностью только числа говорит мне, что это должен быть массивв некотором роде, std :: array или std :: vector.

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

хорошая самостоятельная помощь - использование отладчика для перехода покод.

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