Как: вставить пару в мультикарту, причем один из типов является абстрактным? - PullRequest
2 голосов
/ 04 ноября 2011

Например:

abstract class goal
class priority
class childgoal

multimap<priority, goal> mm;
mm.insert(make_pair(priority(), childgoal());

Я получаю сообщение об ошибке:

cannot declare field 'std::pair<priority, goal>::second'
to be of abstract type 'goal'

Если я правильно помню, Pair использует конструктор по умолчанию для создания секунды перед назначением, что является причинойдистрессЯ могу ошибаться, но это объяснило бы ошибку.

Как мне обойти это ... как я могу выполнить вставку в мультикарту (или, возможно, карту в этом отношении), когда один из типов является абстрактным

Ответы [ 3 ]

4 голосов
/ 04 ноября 2011

Вы можете создать карту указателей:

#include <memory>
#include <map>

class Base { };
class Derived1 : public Base { };
class Derived2 : public Base { };

typedef std::shared_ptr<Base> MyPtr;
typedef std::multimap<Key, MyPtr> MyMap;

int main()
{
  MyMap m { { Key(1), MyPtr(new Derived1) }, { Key(2), MyPtr(new Derived2) } };
}

Для унифицированного синтаксиса инициализации требуется поддержка C ++ 11.В более старых версиях вы можете вместо этого вставить:

m.insert(MyMap::value_type(Key(1), MyPtr(new Derived1)));

Если никому больше не нужны сопоставленные объекты, вы можете использовать вместо std::unique_ptr<Base>.Простой вопрос изменения typedef.

1 голос
/ 04 ноября 2011

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

Но каждый раз, когда вы хотите использовать полиморфизм, у вас должен быть автомат для использования указателя на базу (ссылка на базу также работает, если я правильно помню). Предполагая, что childgoal публично наследует от цели, следующие утверждения верны:

  • детская цель является целью
  • указатель на цель может указывать на цель или дочернюю цель (или на любой производный класс)
  • но цель экземпляр is-NOT-a childgoal

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

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

abstract class goal;
class priority;
class childgoal : public goal;

typedef std::tr1::shared_ptr<goal> goalPtr; //sadly I think std::tr1 is not a multiplatform namespace 

multimap<priority, goalPtr> mm;
goalPtr tmpChildGoal(new childgoal()); //always use named shared pointer !
mm.insert(make_pair(priority(), tmpChildGoal);
0 голосов
/ 17 августа 2015

Очень просто сказать: абстрактные классы могут использоваться только как указатели или ссылки.Если вам нужен контейнер полиморфного экземпляра вашего класса, вам нужно хранить указатель или, что лучше, умный указатель, возможно, unique_ptr.

...