在std :: map中继承,基类为value

时间:2013-12-24 13:02:20

标签: c++ inheritance map stl

这是一段代码:

class Base {
    public:
        long index;
};
class Derived : public Base {
    public:
        bool value;
};

void call(map<char *, Base *> *base) {
    map<char *, Base *>::iterator it = base->begin();
    cout << it->second->index << endl;
}
void test(void) {
    map<char *, Derived *> *d = new map<char *, Derived *>;

    call(d);
}

编译器警告错误:

error C2664: 'call' : cannot convert parameter 1 from 'std::map<_Kty,_Ty> *' to 'std::map<_Kty,_Ty> *'
1>        with
1>        [
1>            _Kty=char *,
1>            _Ty=Derived *
1>        ]
1>        and
1>        [
1>            _Kty=char *,
1>            _Ty=Base *
1>        ]
1>        Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast

我理解为什么会发生这种错误。 我不明白如何使它工作。什么样的演员以及如何使用它?

UPD

我很抱歉不准确,让我解释一下细节。 我有两组由ClassA和ClassB表示的数据。 这两个类都有一个共同的成员 - 例如“索引”。 两组都被包装成一张地图(特别感谢Rob对char *进行了重大修正):

std::map<char, ClassA>
std::map<char, ClassB>

有时我需要遍历两个映射以获得公共成员“index”的值。 我正在努力避免代码重复,并只使用一个函数迭代两个映射。

我以为我可以用一个普通成员提取一个超类,然后用这样的参数创建一个函数:

std::map<char, SuperClassAB>

std::map<char, SuperClassAB>::iterator

但看起来这是一个坏主意。

UPD2

一个聪明的家伙给了我解决方案:

template <class T>
void call(map<char, T> *base) {
    map<char, T>::iterator it = base->begin();
    cout << it->second->index << endl;
}
void test(void) {
    map<char, Derived *> d;
    call(&d);
}

4 个答案:

答案 0 :(得分:1)

如果您的目标是在派生类上以某种方式“操作”,请在基类上创建一个虚方法并覆盖它以获得所需的特定行为:

class Base
{
public:
   long index;
   virtual void doSomething()
   {
      // Do something with index
      cout << index << endl;
   }
};

class Derived : public Base
{
public:
   bool value;

   virtual void doSomething()
   {
      // Do something with value
      cout << value << endl;
   }
};

// NOTE:  I removed the pointer and made it a ref.
// NOTE:  I made it "const" because you probably don't want to alter the
// map.  If you do...
void call(const map<char *, Base *>& base)
{
   map<char *, Base *>::const_iterator it = base.begin();
   //   cout << it->second->index << endl;
   it->second->doSomething();
}

void test(void)
{
   map<char *, Base *> d;
   // Push some members into d...I didn't, but you should
   // if you want call(...) to be meaningful.
   call(d);
}

这有用吗?

答案 1 :(得分:1)

您无法投射这些类型。 map<char*,Base*>map<char*,Derived*>stringfloat不同。

最简单的事情是在test()内填充map<char*,Base*>,然后用call调用virtual。在Base中提供virtual方法(可能是纯Derived),并在transform中实施这些功能。

您可以尝试从map<char*,Derived*> map<char*,Base*> Base* Derived,但为了做到这一点,您的仿函数需要:

  1. 绝对知道 static_cast实际指向Base个对象,并使用virtual
  2. 使dynamic_cast多态(通常通过实现{{1}}析构函数),并使用{{1}}

答案 2 :(得分:1)

您可能需要容器来存储基类指针而不是派生类指针。

E.g。map<char *, Base *> *d;

此后,您应该使用所需的任何派生类型的元素填充地图。 E.g。

char keyA = 'A';
char keyB = 'B';
(*d)[&keyA] = new Derived();
(*d)[&keyB] = new AnotherDerived();

这会在你的实例中起作用吗?

顺便说一下,为什么你使用char *因为关键似乎是一个奇怪的选择。

答案 3 :(得分:1)

似乎没有人建议这样做,但您也可以将call作为功能模板。

    template <class Type>
    void call(const std::map<char*,Type*> & base)
    {
        static_assert(std::is_base_of<Base, Type>::value,
                      "Function is only callable with maps "
                      "whose mapped_type is derived from Base");
        /* More stuff */
    }

这样,该函数可以使用BaseDerived以及从Base派生的任何其他内容来调用。