используя l-значение с абстрактным классом - PullRequest
0 голосов
/ 27 октября 2010

У меня проблема с вызовом метода с l-значением абстрактного класса. Определение класса:

class SimulatorSequenceItemBase {
public:
    SimulatorSequenceItemBase();
    virtual ~SimulatorSequenceItemBase();

    virtual uint32_t GetResult(uint32_t p_nSite) = 0;
    virtual bool MoveNext(SimulatorSequenceItemBase& p_rNext) = 0;
}

SimulatorSequenceItemBase имеет несколько подклассов. Существуют последовательности (для циклов) и элементы для цикла for.

Я хочу перебрать последовательность и сосчитать шаги, используя:

uint32_t nI = 0;
SimulatorSequenceItemBase root = forSeq; // forSeq is an instance of a subclass of SimulatorSequenceItemBase 
while(root.MoveNext(root))
{
    ++nI;
    std::cout << root.GetResult(0);
}

Корень изначально ссылается на корень, и при каждом вызове MoveNext ссылка должна быть скорректирована до следующего элемента.

Код, упомянутый выше, не работает, потому что root не может быть выделен, так как тип root абстрактный. Но если бы я сделал указатель root, значение не может быть изменено в MoveNext.

Как я могу это исправить? Можно менять любой код, но идея должна оставаться прежней.

Ответы [ 3 ]

2 голосов
/ 27 октября 2010

Понятия не имею, что должно быть forSeq, но что не так с

SimulatorSequenceItemBase& root = forSeq; // note that &

Поскольку, согласно комментарию, вам нужно сбросить root для ссылки на разные объекты, вам придется использовать указатели:

SimulatorSequenceItemBase* root = forSeq; note the *
while(root.MoveNext(root))
{
    // ...
}

Однако, чтобы сбросить MoveNext() root, необходимо взять указатель на каждую ссылку:

bool MoveNext(SimulatorSequenceItemBase*& p_rNext) // note the *&
1 голос
/ 27 октября 2010

Причина, по которой вы столкнулись с проблемой, заключается в том, что строка SimulatorSequenceItemBase root = forSeq; фактически создает в стеке новый экземпляр SimulatorSequenceItemBase (сплайсированная копия forSeq).Поскольку у вас есть чисто виртуальная функция, вы не можете создать экземпляр базового класса.Что вам нужно сделать, это изменить его, чтобы использовать ссылку или указатель:

SimulatorSequenceItemBase *pRoot = &forSeq;

while (pRoot->MoveNext(pRoot))
{
    ++nI;
    std::cout << pRoot->GetResult(0);
}

Редактировать После вашего комментария я предлагаю рефакторинг вашего кода, чтобы это было примерно так:

SimulatorSequenceItemBase *pNode = &forSeq;
while (pNode != NULL)
{
    ++nI;
    std::cout << pRoot->GetResult(0);

    pNode = pNode->MoveNext();
};
0 голосов
/ 27 октября 2010

ОК, прежде всего. Почему MoveNext вообще принимает аргумент? Это не должно.

virtual bool MoveNext() = 0;

, а затем

SimulatorSequenceItemBase& root = forSeq;
while(root.MoveNext())
{
   ++nI;
}
...