ひだかです。
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