質問

次のような関数の子実装を呼び出すために、純粋な仮想親クラスが必要です:

class parent
{
  public:
    void Read() { //read stuff }
    virtual void Process() = 0;
    parent() 
    {
        Read();
        Process();
    }
}
class child : public parent
{
  public:
    virtual void Process() { //process stuff }
    child() : parent() { }
}

int main()
{
   child c;
}

これは機能するはずですが、リンクされていないエラーが表示されます:/これはVC ++ 2k3を使用しています

それは機能しないはずです、私は間違っていますか?

役に立ちましたか?

解決

次の記事のタイトルはそれをすべて示しています。 >。

他のヒント

別の方法として、オブジェクトを作成するファクトリメソッドを作成し、コンストラクタをプライベートにします。ファクトリメソッドは、構築後にオブジェクトを初期化できます。

一般的には機能しますが、純粋な仮想基本クラスのコンストラクター内の呼び出しでは機能しません。基本クラスが構築された時点では、サブクラスのオーバーライドは存在しないため、呼び出すことはできません。オブジェクト全体が構築された後に呼び出す限り、動作するはずです。

呼び出しがコンストラクター内にあるためです。派生クラスは、コンストラクターが完了するまで有効ではないため、コンパイラーはこれを正しく行うことができます。

2つの解決策があります:

  1. 派生クラスのコンストラクターでProcess()を呼び出します
  2. 次の例のように、Processの空の関数本体を定義します。
class parent
{
  public:
    void Read() { //read stuff }
    virtual void Process() { }
    parent() 
    {
        Read();
        Process();
    }
}

さらに一歩進むと、次のような関数を導入できます

class parent
{
    public:
        void initialize() {
            read();
            process();
        }
}

オブジェクトが完全に構築された後に仮想メソッドを呼び出すオブジェクト内にラップする必要があります。

class parent
{
  public:
    void Read() { /*read stuff*/ }
    virtual void Process() = 0;
    parent()
    {
        Read();
    }
};

class child: public parent
{
  public:
    virtual void Process() { /*process stuff*/ }
    child() : parent() { }
};

template<typename T>
class Processor
{
    public:
        Processor()
            :processorObj() // Pass on any args here
        {
            processorObj.Process();
        }
    private:
        T   processorObj;

};




int main()
{
   Processor<child> c;
}

表面的の問題は、まだ知られていない仮想関数を呼び出すことです(オブジェクトは親から子へと構築されるため、vtableも同様です)。コンパイラはそれについて警告しました。

必須の問題は、私が見る限り、継承によって機能を再利用しようとすることです。これはほとんど常に悪い考えです。設計上の問題、いわば:)

本質的に、テンプレートメソッドパターンをインスタンス化して、 what when から分離します。最初にデータを(何らかの方法で)読み取り、次に処理します(何らかの方法)。

これはおそらく、集計でより適切に機能します。適切なタイミングで呼び出されるように、Processing関数をTemplateメソッドに渡します。読み取り機能でも同じことができるかもしれません。

集約は2つの方法で実行できます:

  1. 仮想関数の使用(つまり、ランタイムバインディング)
  2. テンプレートの使用(つまり、コンパイル時バインディング)

例1:ランタイムバインディング

class Data {};
class IReader    { public: virtual Data read()            = 0; };
class IProcessor { public: virtual void process( Data& d) = 0; };

class ReadNProcess {
public:
    ReadNProcess( IReader& reader, IProcessor processor ){
       processor.process( reader.read() );
    }
};

例2:コンパイル時バインディング

template< typename Reader, typename Writer > // definitely could use concepts here :)
class ReadNProcess {
public:
     ReadNProcess( Reader& r, Processor& p ) {
         p.process( r.read() );
     }
};
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top