Copy constructor and implicit type conversion
#include <iostream> class Complex { private: const double re; const double im; public: Complex(double r = 0.0, double i = 0.0) : re(r), im(i) { std::cout << "constructor: " << *this << std::endl; } Complex(const Complex& c) : re(c.re), im(c.im) { std::cout << "copy constructor: " << *this << std::endl; } ~Complex() {} Complex operator=(const Complex& c) // field が immutable だと、デフォルトの代入はできない { return Complex(c); } friend Complex operator+(const Complex&, const Complex&); friend std::ostream& operator<<(std::ostream& s, const Complex&); }; Complex operator+(const Complex& c1, const Complex& c2) // const .. & がないと { // copy constructor が呼ばれる return Complex(c1.re + c2.re, c1.im + c2.im); } std::ostream& operator<<(std::ostream& s, const Complex& c) { return s << "(" << c.re << ", " << c.im << ")@" << &c; } template<class T> T add(const T& a, const T& b) { return a + b; } int main() { double x = add(10, 20); std::cout << x << std::endl; Complex c1(10.0, -10.0); Complex c2(-2); std::cout << "add<>()" << std::endl; Complex c3(add(c1, c2)); // same to add<Complex>(c1, c2) std::cout << c3 << std::endl << std::endl; std::cout << "operator+()" << std::endl; Complex c4(c1 + c3); std::cout << c4 << std::endl << std::endl; std::cout << "operator+(), substitution" << std::endl; Complex c5 = c2 + c4; Complex c6; c6 = c5; std::cout << c5 << std::endl << std::endl; c6 = 0; add<Complex>(1, 2); return 0; }
実行結果
30
constructor: (10, -10)@0x22ccb0
constructor: (-2, 0)@0x22cca0
add<>()
constructor: (8, -10)@0x22cc90
(8, -10)@0x22cc90operator+()
constructor: (18, -20)@0x22cc80
(18, -20)@0x22cc80operator+(), substitution
constructor: (16, -20)@0x22cc70
constructor: (0, 0)@0x22cc60
copy constructor: (16, -20)@0x22cc50
(16, -20)@0x22cc70constructor: (0, 0)@0x22cc30
copy constructor: (0, 0)@0x22cc40
constructor: (2, 0)@0x22cc10
constructor: (1, 0)@0x22cc00
constructor: (3, 0)@0x22cc20
operator+を外で2項関数として定義する理由は、
第一引数に関して暗黙の型変換を有効にするため。
ようするに、
Complex(0,1)+1 も
1+Complex(0,1) も書けるようにするため。
上の方はどうでもよくて、面白いのは最後のところ。
引数のデフォルト値と演算子オーバーロードができると、こんなこともできるんですね...