Полиморфная переменная-член

Вчера я получил элегантный ответ на мой вопрос о члены полиморфного объекта.

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

#include <iostream>
#include <math.h>

using std::cin;
using std::cout;
using std::endl;class Com
{
public:
virtual void setReady()
{
cout << "Com" << endl;
}
};

class DerivedCom : public Com
{
public:
void setReady()
{
cout << "DCom" << endl;
}

void somethingElse()
{
cout << "else" << endl;
}

};

class BaseClass
{
public:
Com* com;

public:
BaseClass(Com* c = new Com) : com(c)
{
}

virtual void setReady()
{
com->setReady();
}
};

class DerivedClass : public BaseClass
{
// the call to somethingElse() won't compile if I leave out this declaration
protected:
DerivedCom* com;

public:
DerivedClass() : BaseClass(new DerivedCom)
{
}

void setReady()
{
// This line causes a segfault if I put in the declaration earlier
this->com->setReady();

// This line won't compile if I leave out the declaration earlier
this->com->somethingElse();
}
};

int main()
{
DerivedClass* inst = new DerivedClass();

inst->setReady();
return 0;
}

Проблема в том, что DerivedClass::com на самом деле типа DerivedCom но я не могу получить доступ к любому DerivedCom-специфичные методы, так как компилятор их не найдет. Если я добавлю дополнительную декларацию DerivedCom* com, компилятор найдет методы, но я получаю ошибки сегментации.

0

Решение

Удалить эту дополнительную декларацию.

Если вы уверены, что Com* это DerivedCom* тогда ты можешь static_cast Это.

static_cast<DerivedCom*>(this->com)->somethingElse();

Это, вероятно, приведет к сбою, если вы ошибаетесь. Так что если вы не уверены, то вы можете dynamic_cast Это

DerivedCom* dcom = dynamic_cast<DerivedCom*>(this->com);
if (dcom)
dcom->somethingElse();

dynamic_cast вернет NULL, если объект не того типа, который вы просили.

3

Другие решения

Причиной ошибок сегментации является то, что вы не объявлять переменную снова с другим типом, вы на самом деле определение нового указателя в производном классе тот, который никогда не инициализируется. таким образом this->com->... получит доступ к производному классу com и сбой, так как это неинициализированный указатель.

Что вы пытаетесь сделать, это изменить тип указателя члена. Вы можете сделать это путем создание типа указателя на член в качестве переменной шаблона, следующее

template <class ComType>
class BaseClassTemplate
{
ComType* com;
...;
};

typedef BaseClassTemplate<Com> BaseClass;

class DerivedClass : public BaseClassTemplate<DerivedCom>
{
...;
};

Однако это делает базовый класс шаблоном, поэтому, чтобы получить его так, как вам нужно, нужно создать экземпляр BaseClass<Com> чтобы получить вашу версию базового класса. Вы можете сделать его производным классом или просто typedef, как я уже показал.

0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector