2017-01-31 13 views
0

Я знаю, что такое использование полиморфизма времени выполнения на объектно-ориентированном языке программирования. Например, базовый класс Superhero был бы полезен для определения основных абстрактных свойств Superhero, которые могут быть унаследованы и расширены в разных супергероях, например Batman.Когда вам нужен указатель базового класса на объект производного класса в C++?

Я также знаю, что мы используем наследование, когда есть is-a отношения, например, Supermanis-a супергероя, и мы можем использовать указатель базового класса, чтобы указать на объект производного класса, например ...

Superhero *h = new Spiderman(); 

действительно.

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

Spiderman *s_man = new Spiderman() 

Какую ситуацию или обстоятельства заставят нас использовать базу указатель класса для хранения объекта класса Child.

Я был бы благодарен, если кто-то может это разъяснить мне.

+0

Напишите одну строку кода, чтобы «удалить» любой 'SuperHero *'. Этого должно быть достаточно, чтобы объяснить, почему «Супергероя * h» будет использоваться. – PaulMcKenzie

+2

Вставьте пример открытия из любой книги OO здесь. – Barry

+2

'Я знаю, что использовать полиморфизм времени выполнения на объектно-ориентированном языке программирования.« Я подозреваю, что вы этого не делаете. Полиморфизм времени выполнения (объектно-ориентированный) может быть достигнут только путем указания на производный объект с базовым указателем (или ссылкой). Когда вы знаете, для чего используется полиморфизм времени выполнения, ответ станет очевидным. – user2079303

ответ

0

Если вы хотите иметь стандартные звонки для всех типов супергероев. Но реализация отличается. Нет синтаксиса здесь:

class Superhero 
{ 
public: 
virtual void changeClothes() = 0; 
} 

class Spiderman : public Superhero 
{ 

public: 
void changeClothes() 
{ 
    body.wear(spideySuit); 
} 

}; 


class Hulk public Superhero 
{ 

public: 
void changeClothes() 
{ 
    body.shorts.TearApart(); 
} 
}; 

SuperHero * spidy = (Superhero *) new Spiderman; 
SuperHero * hulkster = (Superhero *) new Hulk; 

spidey->changeClothes(); 
hulkster->changeClothes(); 
+1

Я не уверен, что это отвечает на вопрос. Ваш пример будет работать так же хорошо, если вы не использовали указатели базового класса. –

0

Рассмотрите список указателей супергероев. Такой список может хранить ссылки (указатели) до new Spiderman(), new Superman() и другие объекты, которые наследуют супергероев.

@lcs предоставила прекрасную иллюстрацию этой концепции.

4

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

std::vector<Superhero*> GetAvengers() 
{ 
    std::vector<Superhero*> avengers; 
    avengers.push_back(new Spiderman()); 
    avengers.push_back(new CaptainAmerica()); 
    avengers.push_back(new IronMan()); 
    avengers.push_back(new Thor()); 
    // ... ad nauseam for three generations of unnecessary standalone films 
    return avengers; 
} 

void FightThanos() 
{ 
    SuperVillan* thanos = new Thanos(); 
    auto Avengers = GetAvengers(); 

    for(auto&& avenger : Avengers) 
    { 
     avenger->SaySomethingSnarky(); 
     avenger->ParticipateInMontageActionSequence(thanos); 
    } 

    // Clean up after the avengers, they're not needed for another 4 years 
    for(auto&& avenger : Avengers) 
    { 
     delete avenger; 
    } 
    avengers.clear(); 
} 
+0

Спасибо. Очень полезно. Я никогда не рассматривал этот сценарий. :) – n00bNietzsche

+1

Просто будьте осторожны с методом 'GetAvengers()', к концу 2019 года это, скорее всего, запустит ['std :: bad_alloc'] (http://en.cppreference.com/w/cpp/memory/ new/bad_alloc), когда вы пытаетесь создать всех. – lcs

+0

+1 для редактирования только для добавления 'avenger-> SaySomethingSnarky()'. Обратите внимание, что для новичков нужно понимать 'SaySomethingSnarky()' и 'ParticipateInMontageActionSequence()' должен быть объявлен в базовом классе Superhero и, возможно, переопределен в дочерних классах. Виртуальные таблицы обрабатывают остальные. –