web-dev-qa-db-ja.com

C ++仮想メソッドをオーバーライドする

私のクラスのユーザーが自分の派生クラスでそれらの実装を提供する機能を提供するためにいくつかのメソッドが仮想として定義されているクラステンプレートがあります。テンプレートクラスには、仮想メソッドを使用するいくつかの非仮想メソッドがあることに注意してください(値を返すはずの仮想クラスは、非仮想クラスで呼び出されます)。

親クラスの仮想メソッドが値を返す必要がある正しいコードの簡単な例を教えてください(ただし、その実装は子クラスで提供されます)、親クラスの仮想メソッドによって返される値は他のクラスで使用されますそのクラスのメソッド。私はどこかを見たので(たとえば、ここ: C++仮想関数を安全にオーバーライド )、これが問題を引き起こす可能性があり、ユーザー定義メソッドは親クラスの仮想メソッドをオーバーライドすることに注意します。

注:私はCode :: Blocksでg ++コンパイラーを使用してプログラミングしています。

編集:ここに要求されたように私が欲しいものの簡単な例:

template<typename T>
class parent {
public:
  // Public methods that user can call
  int getSomething(T t);
  void putSomething(T t, int x);

  // public method that user should implement in his code
  virtual float compute(T t) { }

  // protected or private methods and attributes used internally by putSomething ...
  float doComplexeThings(...); // this can call
};

Compute()メソッドは、ユーザー(子クラス)が実装する必要があります。ただし、このメソッドcompute()は、たとえばputSomething()およびdoComplexeThings()によって呼び出されます。

12
shn

メソッドの署名が同じであることを確認するだけです(const/mutable修飾子と引数の型を含む)。純粋な仮想定義を使用して、サブクラスで関数をオーバーライドできなかった場合にコンパイラエラーを引き起こすことができます。

class parent {
public:
  // pure virtual method must be provided in subclass
  virtual void handle_event(int something) = 0; 
};

class child : public parent {
public:
  virtual void handle_event(int something) {
    // new exciting code
  }
};

class incomplete_child : public parent {
public:
  virtual void handle_event(int something) const {
    // does not override the pure virtual method
  }
};

int main() {
  parent *p = new child();
  p->handle_event(1); // will call child::handle_event
  parent *p = new incomplete_child(); // will not compile because handle_event
                                      // was not correctly overridden
}
21
mschneider

コンパイラでC++ 11機能を使用できる場合は、override特殊識別子を使用してオーバーライドにタグを付けることができます。

 float compute() override;

派生クラスの上記の行は、関数がベースのメンバー関数をオーバーライドしないため、コンパイラエラーを引き起こします(シグネチャが正しくない、引数が不足している)。ただし、これは各派生クラスで行う必要があることに注意してください。これは、基本クラスから課すことができるソリューションではありません。

基本クラスからはforce関数を純粋に仮想化することによってのみオーバーライドできますが、これによりセマンティクスが変更されます。 avoidオーバーライド中の問題ではなく、forcesすべてのケースでオーバーライドします。私はこのアプローチを避けます、そしてあなたがそれに従い、基本型の賢明な実装がある場合、関数を仮想にしますand定義を提供して、派生クラスの実装が関数を呼び出すことができるようにします基本タイプ(つまり、実装を強制しますが、最も単純なケースでは、呼び出しを親に転送します)

この質問は2013年に行われます。かなり古いですが、回答に存在しない新しいものを見つけました。

3つの概念を理解する必要がありますoverloadoverwrite、およびhide

簡単に言えば、基本クラスから継承関数をオーバーロードする必要があります。ただし、オーバーロードは、同じスケールでこれらすべての関数を必要とする関数に複数の動作を追加するメカニズムです。しかし、仮想関数は明らかにBaseクラスにあります。

class A {
public:
  virtual void print() {
    cout << id_ << std::endl;
  }
private:
  string id_ = "A";
};

class B : A {
public:
  using A::print;
  void print(string id) {
    std::cout << id << std::endl;
  }
};

int main(int argc, char const *argv[]) {
  /* code */
  A a;
  a.print();
  B b;
  b.print();
  b.print("B");
  return 0;
}

追加sing A :: print;派生クラスで作業を行います!

overloadinheritanceの背後にある哲学が異なるため、良い考えではないと思いますが、それらを一緒にネストすることは良い考えではないかもしれません。

0
yuan