1

問題の解決策を見つけるためにすでに多くの検索を行いましたが、次のコードを機能させる方法が見つかりません。

バックグラウンド

私はあらゆる種類のアーカイブを表すクラス構造を作成しました (私の実際のケースでは、これはアーカイブである可能性のある FileRepository になります)。したがって、アーカイブを表す純粋仮想クラス構造を定義しました。

アーカイブは実際にはディレクトリであり、ディレクトリは実際にはエンティティ (この場合は Base) です。このアーカイブ内のファイルもエンティティ (ベース) になります。これらのクラスは、実際の実装のインターフェースとして使用されます。

コードには、これらのクラスの My... 実装が表示されます。

問題

MyDirectory 実装は、ディレクトリが返されることを期待するベースのgetParentメソッドを上書きします。実際には、MyDirectory 実装は MyDirectory のみを親として持つことができるため、新しい実装は Directory ではなく MyDirectory を返します。ここで C++ がエラー メッセージをスローします。

MyDirectory クラスを宣言する前に、MyBase クラスのgetParentメソッドを上書きしているため、コンパイラは MyDirectory が実際にディレクトリであることを知りません。

また、MyDirectory も特定の MyDirectory メソッドを (getAbsolutePath として) 呼び出す必要があるため、戻り値の型を Directory ではなく MyDirectory にする必要があります。(そして static_cast も機能しませんでした:()

私の問題を解決する方法、ヒントがあれば幸いです:)

詳細を編集する

問題は実際には複雑な継承グラフです。問題は、MyDirectory が MyBase を継承しているが、MyBase のメソッドが MyDirectory を返すことです。ただし、Base クラスは Directory を返す必要がありますが、宣言時に、c++ は MyDirectory が実際に Directory であることを知りません。MyDirectory が MyDirectory インスタンスを返すことができ、 Directory インスタンスを返す必要がないことを解決しようとしています。

// Just an example code - actually is separated in .h and .cpp and cleaner and and and... :)

class Directory;
class MyDirectory;

class Base {
public:
    /// Returns the parent directory
    virtual Directory *getParent()=0;
};

class Directory : virtual public Base {
public:
};

class Archive : virtual public Directory {
public:
};

// ---------------------------------

class MyBase : virtual public Base {
public:
    /// Constructor
    MyBase(int i, int j, int k) {}

    /// Returns the parent directory
    MyDirectory *getParent() { return NULL; }

    /// Returns the parent directory
    virtual const char *getAbsolutePath() const { return "my full path"; }
};

class MyDirectory : virtual public Directory, public MyBase {
public:
    /// Constructor
    MyDirectory(int i, int j) : MyBase(i, j, i+j) {}

    /// Returns the parent directory (not really, I know! Just an example)
    virtual const char *getAbsolutePath() const { return getParent()->getAbsolutePath(); }
};

class MyArchive : virtual public Archive, public MyDirectory {
public:
    /// Constructor
    MyArchive(int i) : MyDirectory(i, i) {}
};
4

1 に答える 1

1

共変リターンタイプは便利です。

GetMyParent()を返す書き込みMyDirectoryGetParentとが表示さGeyMyParentれるまでの実装を延期してから、を呼び出します。MyDirectoryGetParentGetMyParent

必要に応じて完全に共変にMyDirectoryすることもできますがGetParent、気にしません。代わりにオーバーライドが必要な場合は、GetParent後にオーバーライドしないでください。MyBaseGetMyParent

誤って呼び出さないように、GetParentプライベートにすることもできます。がある場合は、代わりMyBaseに電話してください。GeyMyParent

これによりコードの保守が煩わしい場合は、オーバーライドを使用して呼び出す関数を選択するcalpedの無料関数を記述GetParentします。無料の関数が嫌いな場合は、呼び出す関数を選択する非仮想メソッドを追加します(2つ、1つは1つ、もう1つは1BaseMyBase)。

free function / non-virtualメソッドの唯一の問題は、マルチパスツリーがそれを混乱させ、あいまいさをもたらす可能性があることです。が必要であるGetMyParent()ことがわかっている場合は、電話をかけます。メソッド/フリー関数のばかげた数のオーバーライドの要件、またはtiを自動的に発生させるために必要なテンプレートハッカーは、それだけの価値はありません。MyBaseMyDirectory*

于 2013-02-14T13:00:08.023 に答える