我无法从指针到派生类以及从指针到指针到基类进行分配?
I can't assign from pointer to pointer to derived class and pointer to pointer to base class?
可能重复:
衍生**到基础**之间的转换
在学习了几年Python之后,我又回到了C++领域,遇到了一堵强类型墙。我认为我很好地处理了基类和派生类指针之间的基本多态性和类型转换(例如,派生类的指针可以类型转换为其基类的指针吗?),但这里有一个难题:为什么我不能将指向派生类的指标分配给它基类的p-to-p?
为了获得更多的上下文信息(也许还有一些不那么狡猾的技巧),下面是我尝试做的一个简化版本。我想要一个指向对象的指针列表(从一个类派生)和一个标识它们的字符串(即map<string, obj*>
)。然后,一组组件将传递一个标识字符串和位置的列表,以存储指向相应对象(即map<string, obj**>
)的指针。然后,我应该能够通过字符串id找到合适的对象,并填写合适的指针供组件后续使用。实现这一点的简化代码是
#include <map>
#include <string>
using namespace std;
class base
{
};
class derived: public base
{
};
typedef map<string, base**> BasePtrDict;
typedef map<string, base*> BaseDict;
int main(int argc, char* argv[])
{
base b1, b2;
derived d;
derived* d_ptr;
BaseDict base_dict;
base_dict["b1"] = &b1;
base_dict.insert(make_pair("b2",&b2)); // alternate syntax
base_dict["d"]= &d;
BasePtrDict ptr_dict;
ptr_dict["d"] = &d_ptr;
for (auto b = ptr_dict.begin(); b != ptr_dict.end(); b++)
*(b->second) = base_dict[b->first];
return 0;
}
这在ptr_dict["d"] = &d_ptr;
处遇到编译错误。为什么?在C++范式中,我应该做什么?我真的需要到处做难看的(不安全的)reinterpret_cast<base>()
吗?
您正在丢失将base *
强制转换为derived *
所需的信息。
考虑derived
从多个基类继承的情况,因此强制转换需要调整指针值。则用于指向基pb
的指针的derived *pd = static_cast<derived *>(pb)
将自动应用指针调整。
但是derived *pd; base **ppb = &pd; *ppb = *pb
将无法应用指针调整,因此这是不合法的。
你应该做的是:
base *b_ptr;
... // existing code
derived *d_ptr = static_cast<derived *>(b_ptr);
考虑如果允许将derived**
视为base**
:会启用什么
class base
{
};
class derived: public base
{
public:
int boom;
}
void light_the_fuse( base** pb)
{
*pb = new base;
}
int main()
{
derived* pd = NULL;
light_the_fuse( &pd);
pd->boom = 42; // uh oh, `pd` points to a `class base`...
return 0;
}
为了进行从子到基的转换,需要将类型关联起来。对于derived**
到base**
,这意味着derived*
是base*
的子级,这显然不是真的,因为它们是正交指针类型(恰好指向相关类)。
您应该能够用static_cast
而不是reinterpret_cast
来解决这个问题:
ptr_dict["d"] = &static_cast<base*&>(d_ptr);
将derived*
直接转换为base*
是可以的,但这不是您要尝试的。您正在尝试执行derived**
到base**
,这不是隐式强制转换。除此之外,我想问一下为什么?我甚至会问你是否真的需要三分球,但需要双分球?
更换会简单得多
derived* d_ptr;
带有
base* d_ptr;
当您可能需要应用dptr的确切类型时,可以随时使用强制转换,但当然,面向对象的原则表明,这种情况应该非常罕见。
不能也不应该将Derived**
分配给Base**
,因为它不安全。如果强制转换被允许,那么它将允许Derived*
指向非Dervied
类型的类型。考虑以下内容:
class Base {};
class Derived: public Base {};
class Other: public Base {};
...
Derived derived;
Derived* derived_p = &derived; // derived_p points to derived.
Derived** derived_pp = &derived_p; // derived_p points to derived.
// derived_pp points to derived_p.
Base** base_pp = derived_pp; // derived_p points to derived.
// base_pp points to derived_p.
Other other;
Other* other_p = &other; // other_p points to other.
*bpp = op; // base_pp points to derived_p.
// derived_p points to other.
如果上述代码有效,则允许Derived* derived = new Other()
。
不幸的是,我不太确定要完成什么,所以我无法提供替代的解决方案。
这几乎类似于"为什么我需要一个reinterpret_cast来将Fred**const转换为void**const?"?
指向两种不同对象类型的指针基本上是不兼容的。但是,也有例外
Derived*
到Base*
。。。Derived和Base是相关的,因此允许转换(在类型转换为Base*
之后,指针实际上指向Base
类型的对象T*
到void*
-允许(参见上面的链接)
但是没有理由允许D**
转换为B**
,因为B*
和D*
本质上是不同的类型。
- 如何使用基类指针引用派生类成员
- 使用基类指针创建对象时,缺少派生类析构函数
- 如果基类包含双指针成员,则派生类的构造函数
- 使用基类指针调用基类的值构造函数的语法是什么?
- 如何在基类指针向量的元素上应用重载的多态函数
- 如何使用 std::make_shared 创建基类类型的智能指针?
- 如何在不使用指针的情况下将派生类的对象作为参数传递给基类中的函数?
- 指向基类派生类的 std::unique_ptr 的指针
- 当目标指针不是基类的类型时,为什么允许dynamic_cast为多态类生成 null 指针?
- 如何在成为指向基类的指针后保留对子类方法的使用?
- 派生类是从基类继承 v 指针并仅使用它,还是也有自己的 v 指针?
- std::variant vs指向C++中异构容器基类的指针
- 模板化函数或具有指向基类的指针的函数
- 指向基类的唯一指针
- C++函数解析基类指针到派生类指针
- 指向基类的指针的 std::vector 的深层副本
- 在将派生类指针类型转换为派生类指针后,从基类指针调用派生类函数
- 如何将子类作为函数的参数传递给期望基类,然后将该对象传递到指向这些抽象类对象的指针向量中?
- 无法从指针派生类转换为指针基类(多态性)
- 使用指针基类的=操作符的多态性