将指向派生类指针的指针作为参数传递给期望指向基类指针的构造函数

时间:2013-08-07 08:48:21

标签: c++ inheritance constructor polymorphism

我读过

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

我检查via Ideone以下编译,应该:

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;
}

然而,我相信与我的实际程序中的情况相同,会产生错误(关键字已被替换当然):

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

我意识到发布显式代码会有所帮助,但代码的复杂性(不是由我编写,涉及无数层继承,每个文件包含数十个,各处的朋友类,外部变量等)是-numbing,我甚至不确定要减少什么(相关什么和什么不相关)来获得合理的东西来发布。

我有一个可能有帮助的提示。我发现事先投射到基类有效:

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

当然,我不应该这样做。但是这个有用的事实告诉我,我没有像在构造函数的签名中忘记*那样犯了一些微不足道的错误。

任何人都可以想到一些可能的原因我可能会得到我正在获得的错误,但是当我明确地将派生实例强制转换为基类时却没有?

我正在使用Sun Studio 12 Update 1.


其他详细信息

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

...

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

...

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

因此,重申一下,当我执行以下操作时,上述工作就会起作用。

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

4 个答案:

答案 0 :(得分:1)

从指针到派生到指针到基础的隐式转换不会扩展到指向指针的指针。如果你试过这个,你会得到同样的错误:

struct Base{};
struct Derived: Base {};

void f(Base **p){}

int main()
{
    Derived *dp = 0;
    f( &dp);
}

答案 1 :(得分:1)

考虑以下最小例子:

struct Base {};

struct Derived {};

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

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

  

类型为“指向 cv D的指针”的prvalue,其中D是类类型,可以转换为“指向的指针的prvalue” cv B“,其中BD的基类。如果BD的无法访问或模糊的基类,则需要进行此转换的程序格式不正确。

这意味着转换Base* pB = *ppD;格式正确,但在行(A)中没有隐式转换。如果它是合法的,例如多重继承,虚拟继承或任何其他情况,其中必须调整指向Derived对象的指针的地址以获取指向{{1}类型的子对象的指针,则可能会出现问题。 1}}。

还要考虑以下情况:

Base

答案 2 :(得分:1)

以下代码将编译并运行,因为'Derived'类派生自'Base'类。

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;
}

但是,指向'Derived'类的指针的指针与指向'Base'类的指针的指针不同(也不是派生自)。

有关碗香蕉和苹果的精彩解释,请看这里: Conversion from Derived** to Base**

HTH。

答案 3 :(得分:0)

要么

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

Derived* d = new Derived;
Derived** d_ptr = &d;  // not needed ?
Manager* m = new Manager(d);