将指向一个派生类指针的指针作为参数传递给一个构造函数,该构造函数需要一个指向基类指针的指针 [英] Pass a pointer to a derived class pointer as a parameter to a constructor expecting a pointer to a base class pointer

查看:236
本文介绍了将指向一个派生类指针的指针作为参数传递给一个构造函数,该构造函数需要一个指向基类指针的指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我看过

  • Passing pointer to derived class, to function that expects pointer to base class?

但我的答案似乎不适用于我的问题。

but the answer doesn't seem applicable to my issue.

我选中了通过Ideone 下面的编译,因为它应该:

I checked via Ideone that the following compiles, as it should:

class Base
{
public:
    Base() {}
    virtual ~Base() {}
};

class Derived : public Base
{
public:
    Derived() {}
    virtual ~Derived() {}
};

class Manager
{
public:
    Manager(Base* b) {}
    ~Manager() {}
private:
    Manager() {}
};

int main()
{
    Derived* d = new Derived;
    Manager* m = new Manager(d);
    return 0;
}

但是,我相信在我的实际程序,产生一个错误(关键字已被替换当然):

However, what I believe is the same scenario in my actual program, produces an error (keywords have been replaced of course):

"main.cc", line 551: Error: Could not find a match for Manager::Manager(Derived*) needed in main().

我意识到发布显式代码会有帮助,但代码的复杂性(不是由我写的,涉及无数的继承层,几十个包括每个文件,朋友类无处不在,外部变量等)是心灵麻木,我甚至不知道什么减少(什么是相关的,什么不是)获得

I realize that posting explicit code would help, but the complexity of the code (not written by me, involving countless layers of inheritance, tens of includes per file, friend classes everywhere, extern'ed variables, etc.) is mind-numbing, and I'm not even sure what to reduce (what is relevant and what is not) to obtain something reasonable to post here.

我有一个提示可能会有帮助。我发现转换到基类预先工作:

I have one hint that may help. I found that casting to the base class beforehand works:

Manager* m = new Manager((Base*)d);

当然,我不应该这样做。但是,这个工作告诉我,我没有犯过一些微不足道的错误,如在构造函数的签名中忘记一个 *

Of course, I shouldn't have to do that. But the fact that that works tells me that I haven't made some trivial mistake like forgetting a * in the constructor's signature.

任何人都可能想到一些可能的原因,我可能得到的错误,但我不明白,当我显式转换派生实例到基类

我使用的是Sun Studio 12 Update 1。

I'm using Sun Studio 12 Update 1.

我不知道为什么这很重要,但在我的实际应用中,我正在使用指针指针,例如

I don't know why this would matter, but in my real application I'm working with pointer pointers, e.g.

...

class Manager
{
public:
    Manager(Base** b) {}
    ~Manager() {}
private:
    Manager() {}
};

...

    Derived* d = new Derived;
    Derived** d_ptr = &d;
    Manager* m = new Manager(&d_ptr);

所以,重申一下,上面的工作,当我做以下。

So, to reiterate, the above works when I do the following.

    Manager* m = new Manager((Base**)(&d));


推荐答案

考虑以下最小示例:

struct Base {};

struct Derived {};

int main()
{
    Derived** ppD;
    Base** ppB = ppD; // (A)
}

此代码编译,因为在行(A)中没有隐式转换从 Derived ** 转换为 Base ** 。 [conv.ptr] / 3

This code does not compile, because there's no implicit conversion in the line (A) to convert from Derived** to Base**. [conv.ptr]/3


指向 cv 类型的指针。 D ,其中 D 是类类型,可以转换为类型的指针指向 cv B ,其中 B D 的基类。如果 B 是不可访问或不明确的基类 D ,则需要此转换的程序格式错误。 / p>

A prvalue of type "pointer to cv D", where D is a class type, can be converted to a prvalue of type "pointer to cv B", where B is a base class of D. If B is an inaccessible or ambiguous base class of D, a program that necessitates this conversion is ill-formed.

这意味着转换 Base * pB = * ppD; 形成,但是没有对行(A)中的情况的隐式转换。问题可能发生,如果它是合法的例如多重继承,虚拟继承或任何其他情况下,指向 Derived 的对象的指针的地址必须调整为指向 Base 类型子对象的指针。

This means that the conversion Base* pB = *ppD; is well-formed, but there's no implicit conversion for the case in line (A). Problems could occur if it was legal for example for multiple inheritance, virtual inheritance, or any other situation where the address of a pointer to an object of Derived has to be adjusted to get a pointer to the subobject of type Base.

还要考虑以下情况:

void f(Base** p)
{
    delete *p;
    *p = new Base;
}

int main()
{
    Derived* pDerived = new Derived;
    f(&p); // imagine this was allowed
    // pDerived now points to an object of type Base!
}

这篇关于将指向一个派生类指针的指针作为参数传递给一个构造函数,该构造函数需要一个指向基类指针的指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆