「キャストからフロート」アプローチを定義する答えに進むことができますが、パブリック API を利用して追加の動作を実装する方が良いと思います。
一般に、単純な「キャスト」ではうまくいきません (たとえば、もしMyFloat
だったらどうなりMyMatrix
ますか?)。
friend
以下のアプローチは確かにより冗長ですが、「自分の食べ物を食べる」必要があることを強調しています。つまり、あいまいな暗黙のキャストや関数の束ではなく、独自のパブリック インターフェイスに基づいて追加の動作を実装しようとする必要があります。独自の API を使用する場合: その制限を理解し、変更を加えた場合にメイン クラスの再コンパイルを節約できる可能性があります。
また、クラスへのアクセスをカウントする (または基になる値へのアクセスを制御する) とします。キャスト演算子を使用して、operator float()
とのコードを複製する必要がありますfloat value()
。
というわけで、私のささやかな提案は長くなりますが、私の好みでは、オブジェクト指向の設計原則をよりよく反映しています。
#include<iostream>
class MyFloat {
public:
MyFloat(float value):
m_value(value) { }
float value() const {
return m_value;
}
private:
float m_value;
};
// Eat your own food: implement functions using your public interface
// until proven need to do otherwise. This will help you assess the
// usability of your API.
float operator+(const MyFloat& lhs, const MyFloat& rhs) { return lhs.value() + rhs.value(); }
float operator+(const MyFloat& lhs, float rhs) { return lhs.value() + rhs; }
float operator+(float lhs, const MyFloat& rhs) { return lhs + rhs.value(); }
// See, now I can define another operator without need to recompile my
// class (this could have been placed in another file)
std::ostream& operator<<(std::ostream& os, const MyFloat& mf) {
os<<"MyFloat("<<mf.value()<<")";
return os;
}
int main() {
MyFloat x = 3.5; // would not work if I had declared the constructor as "explicit"
MyFloat y = x + 3.2;
MyFloat z = 3.4 + y;
std::cout<<x<<", "<<y<<", "<<z<<std::endl;
}
出力 (でコンパイルg++ example.cpp -Wall -Wextra
):
MyFloat(3.5), MyFloat(6.7), MyFloat(10.1)