作者: HIDAKA Takahiro
日時: 2002/3/27(00:06)
 ひだかです。

kikwai@... (機械伯爵) wrote:

>  coerceですね。
> 
>  あまり新しいルールを覚えて混乱したくなかったので、詳しいところ
> は読みたくなかったのですが・・・
> 
>  う〜〜〜予想以上にややこしいっす(coerceに対するコメント、終り)

 Numeric を定義しようとしない限り関係ない(とおもう)ので
ぼくは全然調べたこともなかったりします(^_^;

> >  それよりも、もっと面倒なのは暗黙の型変換のせいじゃないでしょうか?
>  C++はクラスインスタンスについては非常にシビアなので、明示的なキャスト
> がなければスーパークラス型にさえなりません。

class Foo {
private:
  int m_i;
public:
  Foo(int i = 0) { m_i = i; }
  Foo operator+(Foo a) {
    Foo(m_i + a.m_i);
  }
};

int main(void)
{
  Foo a, b;
  
  b = a + 1;
}

みたいなのがコンパイルできるはずです。Foo + Foo は定義してあって、
Foo + int は定義していないのですが、Foo(int) のコンストラクタが
あると、暗黙の型変換が起きます。

別の例としては、

class Foo {
private:
  int m_i;
public:
  Foo() { m_i = 0; }
  Foo operator+(int i) {
    Foo(m_i + i);
  }
};

class Bar {
private:
  int m_i;
public:
  Bar() { m_i = 0; }

  operator int() {
    return m_i;
  }
};

int main(void)
{
  Foo f;
  Bar b;
  
  f + b;
}

これは、Foo + Bar の演算は定義してありませんが、Foo + int が
定義されていて、Bar → int へのキャストが定義されています。
そうすると、Foo + Bar は Foo + (int)Bar に暗黙のうちに
変換されます。

 ふつうあまりおきないことのように見えますが、int へのキャストは、
if (b) と書くためなどに、古くから使われています。いまだとこれは
bool へのキャストで書くと思うので大丈夫なんですが。

 古くからC++に触れた人はこのあたりの混乱に嫌気がさしているでしょうし、
新しい仕様にちゃんとマッチした参考書(とくに、古い仕様と新しい
仕様の差分をきちんと記述したもの)の不足もあって、C++の
演算子オーバーロードはややこしい、という定説があるんじゃないかと
思います。

 新しいC++の話としては、先月のCマガジンをみていて、explicit 
キーワードというのがあるそうで、これをつかうと暗黙の型変換を
抑止できるそうです。

class Foo {
private:
  int m_i;
public:
  explicit Foo(int i = 0) { m_i = i; }
  Foo operator+(Foo a) {
    Foo(m_i + a.m_i);
  }
};

int main(void)
{
  Foo a, b;
  
  b = a + 1;
}

> >  でも逆にいうと、演算子の可換性を宣言することができれば、
> > 純粋オブジェクト指向+演算子をちゃんとミックスした言語が
> > 作れそうな気もします。深く考えていませんが。
> 
>  オブジェクト指向主義も、文脈を明瞭にして「理解しやすさ」をもとめたもの
> だと私は思っています。
> 
>  とすると、演算子の可換性(・・・う〜ん、この言葉、初耳です。勉強が足り
> ないな・・・)を宣言してたとすると、果たしてそれが「わかりやすい」文脈
> になるかどうかは、私はちょっと疑問ですけどねぇ・・・

 例えばの話ですが、Complex + Int と Int + Complex は同じ結果に
なることを期待しますよね。ですが、純粋オブジェクト指向に従えば、
前者は Complex クラスのメソッド、後者は Int クラスのメソッドに
なります。これの実装が食い違っていることがややこしさの原因に
なっている場合があるんじゃないかと思ったのです。

 単なる思い付きですし、すでにこれを実装した言語もきっとあると
思うので、流行っていない理由もあるんだろうとも思うんですけどね。

 あと、簡単に思いつく例として、可換ではないもの、たとえば 1 + "string"
とかは救えないわけですし。中途半端といえばそれまでですね。

-- 
ひだかたかひろ  cv8t-hdk@...-net.or.jp