0

我读了

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

通过 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().

我意识到发布显式代码会有所帮助,但是代码的复杂性(不是我编写的,涉及无数层继承,每个文件包含数十个包含,无处不在的朋友类,外部变量等)令人麻木,而且我什至不确定要减少什么(什么是相关的,什么不是)才能获得合理的内容以在此处发布。

我有一个提示可能会有所帮助。我发现预先转换为基类是可行的:

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

当然,我不应该那样做。但它有效的事实告诉我,我没有犯一些小错误,比如*在构造函数的签名中忘记 a 。

谁能想到一些可能的原因,我可能会得到我得到的错误,但不是当我将派生实例显式转换为基类时?

我正在使用 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

4 回答 4

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** 的转换

HTH。

于 2013-08-07T09:15:00.067 回答
1

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

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

void f(Base **p){}

int main()
{
    Derived *dp = 0;
    f( &dp);
}
于 2013-08-07T09:07:42.167 回答
1

考虑以下最小示例:

struct Base {};

struct Derived {};

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

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

“指向cv D的指针”类型的纯右值,其中D是类类型,可以转换为“指向cv B的指针”类型的纯右值,其中B是 的基类D。如果B是 的一个不可访问或模棱两可的基类D,则需要进行此转换的程序格式错误。

这意味着转换Base* pB = *ppD;是格式正确的,但对于 (A) 行中的情况没有隐式转换。如果它是合法的,例如多重继承、虚拟继承或任何其他Derived必须调整指向对象的指针的地址以获取指向类型子对象的指针的情况,则可能会出现问题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!
}
于 2013-08-07T09:12:42.623 回答
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);
于 2013-08-07T09:05:18.557 回答