Использование производной функции от объекта внутри объекта списка - PullRequest
0 голосов
/ 18 сентября 2011

У меня есть два класса, один из которых наследует другой:

class baseClass
{
public:
    virtual void show();
};

void baseClass::show(){cout << "Base class" << endl;}


class derivedClass
{
public:
    void show();
};

void derivedClass::show(){cout << "Derived class" << endl;}

Если я создаю объектativeClass и вызываю функцию show, он правильно печатает «Производный класс».Если я сделаю следующее:

derivedClass b;
baseClass* b;
b=&d;
b->show();

Он снова правильно выведет «Производный класс».Тем не менее, если я составлю список примерно так:

list<baseClass> t;
list<baseClass>::iterator it;
baseClass b;
derivedClass d;
t.push_back(b);
t.push_back(d);

и попытаюсь вызвать show для каждого элемента:

it = t.begin();
it->show();
it++;
it->show();

Вывод для b и d будет "Базовый класс".У меня вопрос: почему он использует только версию show () для baseClass и как я могу заставить его правильно использовать производную версию для объектов производного класса в списке?

Заранее спасибо

Ответы [ 2 ]

1 голос
/ 18 сентября 2011

Вы должны объявить метод show() как virtual, чтобы заставить полиморфизм работать:

class baseClass
{
public:
    virtual void show();
};

void baseClass::show(){cout << "Base class" << endl;}


class derivedClass : public baseClass
{
public:
    virtual void show();
};

void derivedClass::show(){cout << "Derived class" << endl;}

Вы также пропали без вести class derivedClass : public baseClass.

И последняя проблема. Вам нужно использовать указатели.

list<baseClass*> t;
list<baseClass*>::iterator it;
baseClass b;
derivedClass d;
t.push_back(&b);
t.push_back(&d);

и изменить на это:

it = t.begin();
(*it)->show();
it++;
(*it)->show();
0 голосов
/ 18 сентября 2011

Снова правильно выводится «Производный класс».Тем не менее, если я составлю такой список:

Нет.Он не может печатать «Производный класс».Фактически, эта строка:

b=&d;

даст ошибку компиляции , поскольку b не является полиморфным основанием d.

Объявить showкак virtual, в базовом классе:

virtual void show();

Тогда это скомпилируется.

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

list<baseClass> t;

, что неверно.

Объявите его как:

list<baseClass*> t;

и нажмите pointer на объектвот так:

derivedClass d;
derivedClass *pd = new derivedClass;
baseClass b;

t.push_back(&d);
t.push_back(pd); //note there is no `&`
t.push_back(&b);

//use t

//must delete pd
delete pd;

-

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

baseClass *bptr = new derivedClass();
delete bptr;

тогда вы должны определить деструктор baseClass как виртуальный, в противном случае приведенный выше оператор удаления вызовет неопределенное поведение.

Так что сделайте это:

class  baseClass:
{
  //...
  virtual ~baseClass();
};
...