3

与えられた:

class Base:
{
  public:
  ...
  Base operator+( const Base& other );
  Base& scale( float num );
}

class Derived : public Base:
{
  public:
  ...
  Derived( const Base& other );
  float super_math_wizardry();
}

//A user can do the following:

Base b1,b2,b3;
Derived d1,d2,d3;

b3 = b1 + b2;
d3 = d1 + d2;

b3 = b1.scale( 2.0f );
d3 = d1.scale( 3.0f ); //scale returns Base& type that is converted to Derived

float x,y;

x = (d1+d2).super_math_wizardry(); //compiler type error since d1+d2 returns Base type
y = (d1.scale(4.0f)).super_math_wizardry(); //similar compiler error

x = Derived(d1+d2).super_math_wizardry(); //works
y = Derived(d1.scale(4.0f)).super_math_wizardry(); //works

Derived のすべての Base メソッドを再実装することなく (Base メソッドを呼び出して Derived 型を返す Derived メソッドを作成する)、ユーザーがキャストを作成したり、コピー コンストラクターを呼び出したりする必要なく、最初の 2 つのステートメントを機能させる方法はありますか?

編集: すべての派生オブジェクトは (クラスの継承に必要なように) Base オブジェクトのセットにありますが、すべての Base オブジェクトが Derived オブジェクトのセットにあるわけではありません。これらは同じデータ メンバーを持ちますが、派生オブジェクトには、それらのデータ メンバーの 1 つに割り当てられた定数値があります (すべての派生オブジェクトで同じ定数値)。

Base または Derived 固有のメソッドは多数ありますが、ほとんどの演算子と set/get アクセサーは、Base オブジェクトと Derived オブジェクトに対して同じ定義済みの動作を持ちます。私がやろうとしているのは、Derived オブジェクトで Base メソッドを呼び出すときに Derived または Derived& を取得することです (これらの操作は数学的に定義されているため)、Base メソッドを呼び出すときに Base または Base& を取得します。ベース オブジェクト上。

CONTEXT: Base は Matrix クラスで、Derived は Vector (列) クラスです。Derived( const Base& other ) コンストラクターは、単一列 (nx1) のマトリックスから明示的にベクターを取得するために作成されました。

だから私は欲しい:

x = (d1+d2).super_math_wizardry(); //works
y = (b1+b2).super_math_wizardry(); //fails (although possibly at run-time since a nx1 Matrix is a column vector)
4

2 に答える 2

3

あなたのコンテキストを考えると、あなたが抱えている根本的な問題は、Derivedオブジェクトのセットが の下で閉じられていることをコンパイラに通知することだと思いますoperator+。私もあなたも知っていますが、C++ 言語にはそれを表現するための特別な近道はありません。を実装する必要がありますDerived Derived::operator+(const Derived&) const

おそらくDerived(const Base &other)コンストラクターを作成しexplicitます。otherの次元が間違っている場合はおそらく例外がスローされるため、ユーザーが暗黙的に発生することを期待する必要はありません。彼らはそれが正しいことを知る必要があるので、彼らはそれが起こることを望んでいると言わなければならないかもしれません.

于 2012-06-12T20:10:15.003 に答える
2

簡単に言えば、いいえです。

関数の戻り値の型は Base です。コンパイラに求めていることは、実行することと同じです

Derived d1;
Base* b = &d1;
b->super_math_wizardry(); // This is also wrong since we don't know that b can be
                          // a derived class

言語が上記との違いを認識する方法がないため、これを行う方法はまったくありません。

Base* b1 = new Base();
b1->super_math_wizardry(); // This is just plain wrong
于 2012-06-12T20:07:49.640 に答える