std::map 中的继承,基类作为值
Inheritance in std::map with base class as value
这是一个代码:
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
很抱歉不精确,让我解释更多细节。我有两组数据,由 A 类和 B 类表示。这两个类都有一个公共成员 - 例如"索引"。两组都包装成一张地图(特别感谢 Rob 对 char* 进行了重大更正):
std::map<char, ClassA>
std::map<char, ClassB>
有时我需要遍历两个映射以获得公共成员"索引"的值。我试图避免代码重复,只制作一个函数来迭代两个映射。
我想我可以提取一个带有公共成员的超类,并使用如下所示的参数创建一个函数:
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);
}
似乎还没有人建议这样做,但您也可以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 */
}
这样,该函数可以使用Base
、Derived
和从Base
派生的任何其他函数来调用。
不能强制转换这些类型。 map<char*,Base*>
和map<char*,Derived*>
就像string
和float
一样不同。
最简单的方法是test()
简单地填充一个map<char*,Base*>
并用它调用call
。 在Base
(可能是纯virtual
)中提供virtual
方法,并在Derived
中实现这些功能。
您可以尝试从map<char*,Base*>
transform
map<char*,Derived*>
,但为了做到这一点,您的函子需要:
- 绝对知道
Base*
实际上指向一个Derived
对象,并使用static_cast
。 - 使
Base
多态(通常通过实现virtual
析构函数),并使用dynamic_cast
如果您的目标是以某种方式在派生类上"操作",请在基类上创建一个虚拟方法并重写它以获得所需的特定行为:
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);
}
这有帮助吗?
您可能需要容器来存储基类指针,而不是派生类指针。
例如map<char *, Base *> *d;
.
此后,您应该使用所需的任何派生类型的元素填充地图。 例如
char keyA = 'A';
char keyB = 'B';
(*d)[&keyA] = new Derived();
(*d)[&keyB] = new AnotherDerived();
这在您的实例中有效吗?
顺便说一句,你为什么使用char *
作为密钥似乎是一个奇怪的选择。
- 派生类是从基类继承 v 指针并仅使用它,还是也有自己的 v 指针?
- C++ - 无法从基类继承 |提供空值
- C++排除通过派生类中的基类继承的类
- 派生类不从基类继承数据成员
- 如何修复从基类继承两次时"error: no matching function for call to"
- C - 从基类继承,成员函数作为模板参数
- 从C++中的基类继承复制/移动构造函数作为构造函数
- 如何从 c++ 基类继承抽象行为
- 将initalizer列表与从空基类继承的结构一起使用
- 在从抽象基类继承的类中添加方法
- 在 C++ 中进行第 n 次继承后停止从基类继承
- std::bad_weak_ptr 从基类继承 std::shared_from_this 时
- 从基类继承私人成员到派生类C
- 从C 中的空基类继承
- 将从基类继承的构造函数与自定义构造函数混合使用
- 创建从基类继承的对象
- 从只有纯虚拟函数的基类继承
- 在发布模式下禁用从C++中的基类继承
- 可以强制从抽象基类继承的类只在基类中定义公共方法吗
- Qt UI 插槽不是由从基类继承的信号调用的