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

明示的なコードを投稿すると役立つことはわかっていますが、コードの複雑さ (私が書いたものではありません。継承の無数の層、ファイルごとの数十のインクルード、どこにでもあるフレンド クラス、extern された変数など) は気が遠くなるようなものです。そして、ここに投稿するのに合理的なものを得るために何を減らすべきか(何が適切で何が適切でないか)さえわかりません。

役立つかもしれないヒントが1つあります。基本クラスへのキャストが事前に機能することがわかりました。

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

次の最小限の例を考えてみましょう。

struct Base {};

struct Derived {};

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

行 (A) に convert from toへの暗黙的な変換がないため、このコードはコンパイルされませ。[コンバージョンptr]/3Derived**Base**

「 cv へのポインター」D型( はクラス型) の prvalue は、 「cvへのポインター」型( は の基底クラス) のDprvalue に変換できます。が の基底クラスにアクセスできないかあいまいな場合、この変換を必要とするプログラムは形式が正しくありません。 BBDBD

これは、変換Base* pB = *ppD;が整形式であることを意味しますが、行 (A) の大文字と小文字の暗黙的な変換はありません。たとえば、多重継承、仮想継承、またはDerivedtype のサブオブジェクトへのポインターを取得するために のオブジェクトへのポインターのアドレスを調整する必要があるその他の状況で合法である場合、問題が発生する可能性があります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 に答える