-4

現在、基本クラスでconstとして定義されている関数の使用に問題があります。

上記の仮想関数を使用して派生クラスを実装していますが、戻り値はconstではありません。この仮想関数を使用する外部クラスが他にもあるため、基本クラスを変更せずにこれを実装したいと思います。この仮想関数を変更しない理由は、同じ関数を使用する他の派生クラスが存在するためです。

どんな助けでも大歓迎です。

double DerivedClass1::Function()例:で定義された仮想関数である、さまざまな戻り値を持つ派生クラス関数の実装に取り​​組んでいdouble BaseClass::Function() constます。これと同じ機能が使用されてdouble DerivedClass2::function() constおりdouble DerivedClass3::Function() const、私が制御することはできません。基本クラスに変更を加えることなく、または最小限の変更を加えることなく、これを行うにはどうすればよいですか。

4

3 に答える 3

1

私があなたを完全に理解しているかどうかはわかりませんが、おそらくこれがあなたが望むものです:

struct BaseClass {
    virtual double Function() {return const_cast<const BaseClass*>(this)->Function();}
    virtual double Function() const=0;
    virtual BaseClass() {}
};
struct DerivedClass1: public BaseClass {
    virtual double Function() {stuff};
    virtual double Function() const {throw std::logic_error("UNIMPLEMENTED");};
};
struct DerivedClass2: public BaseClass {
    virtual double Function() const {stuff};
};

言うまでもなく、これは非常に悪い考えです。BaseClass実装はconst、で実行したいように、派生クラスによってオーバーライドされていない限り、可変インスタンスを既存の関数にリダイレクトしますDerivedClass1。問題は、を呼び出すFunction()と、const DerivedClass1実行時に例外が発生することです。

于 2012-08-08T23:33:22.087 に答える
1

あなたが持っている:

struct Base {
    virtual double Function() const;
};

struct Derived1 : Base {
    virtual double Function() const;
};

struct Derived2 : Base {
    virtual double Function() const;
};

あなたが欲しい:

struct Derived1 : Base {
    virtual double Function(); // overrides virtual function in base
};

したがって、最初に非定数仮想関数をに追加する必要がありBaseます。そうしないと、何もオーバーライドされません。問題は、基本クラス関数を何として定義する必要があるかということです。中断を最小限に抑えるために、非const参照を介して関数を呼び出すのと同じことを行う必要があります。つまり、const関数を呼び出します。

struct Base {
    virtual double Function() const;
    virtual double Function() { return static_cast<const Base*>(this)->Function(); }
};

struct Derived1 : Base {
    virtual double Function() const;
    virtual double Function();
};

struct Derived2 : Base {
    virtual double Function() const;
    // no need to override non-const Function
};

これでも既存のコードが壊れる可能性があると思います。たとえば、関数のconstバージョンとnon-constバージョンへのポインターを取得した場合、以前は同等に比較されていましたが、現在はそうではありません。

typedef double (Base::*constfunc)() const;
typedef double (Base::*mutfunc)();
((mutfunc)(constfunc(&Base::Function)) == (mutfunc(&Base::Function))); // was true, now false

クラスの一般的なユーザーにとってBase、新しい関数を追加することはおそらく無害です。

ただし、「上記の仮想関数を使用しているが、戻り値がconstでない」と言うと、関数doubleのconstバージョンを使用しても、関数の例にはすでにconst以外の戻り値()があります。したがって、回答ではこれに対処できません。実際のユースケースを隠すことで、実際のコードをより適切に反映する例よりも悪い回答が得られる可能性があります。

于 2012-08-08T23:48:20.727 に答える
0

仮想ベースメソッドをオーバーライドする派生メソッドは、の使用を含め、ベースメソッドとまったく同じシグネチャを使用する必要constがあります。そうしないと、派生メソッドは、オーバーライドするのではなく、ベースメソッドを非表示にするだけです。オーバーライドする場合は、派生クラスの署名を変更できません。

于 2012-08-08T23:22:35.310 に答える