C++変換コンストラクタ:他のタイプを現在のクラスのタイプに変換

7002 ワード

技術交流QQ群:1027579432、あなたの参加を歓迎します!
1.C++変換コンストラクタ:他のタイプを現在のクラスのタイプに変換
  • C/C++では、異なるデータ型間で互いに変換することができる.自動タイプ変換(暗黙タイプ変換)と呼ばれる変換方法をユーザーが指定する必要はなく、ユーザーが強制タイプ変換と呼ばれる変換方法を明示的に指定する必要があります.
        //         
        int a = 6;
        a = a + 3.12;  //                    
        //         
        int b = 100;
        int *p = &b;
        float *ptr = (float *)p;  //  int *   float *           
    
  • 自動タイプ変換でも強制タイプ変換でも、コンパイラが変換方法を知っていることが前提です.たとえば、小数点を整数に変換すると小数点の後ろの数字が消去され、int*をfloat*に変換するとポインタの値が簡単にコピーされるだけで、これらのルールはコンパイラに内蔵されており、コンパイラには伝えられていません.つまり、コンパイラが変換ルールを知らないと変換できないので、強制タイプを使っても無駄です.次の例を見てください.
        #include "iostream"
    
        using namespace std;
    
        //                  ,         
        class complex{
            public:
                complex():m_real(0.0), m_img(0.0){}
                complex(double real, double img):m_real(real), m_img(img){}
            public:
                friend ostream & operator<< (ostream &out, const complex &c); //     
            private:
                double m_real;
                double m_img;
        };
    
        ostream & operator << (ostream &out, const complex &c){
            out << c.m_real << "+" << c.m_img << "i";
            return out;
        }
    
        int main(){
            complex a(10.0, 20.0);
            a = (complex) 25.5;  //   ,    
            return 0;
        }
    
  • 上の例では、25.5は実数、aは複素数であり、25.5をaに付与すると、aの実部は25.5になり、虚部は0になることが望ましい.しかし、コンパイラはこの変換ルールを知らず、コンパイラの処理能力を超えているため、変換に失敗し、強制タイプ変換を加えても無駄である.幸いなことに、C++では、ユーザーが他のタイプを現在のクラスタイプに変換したり、現在のクラスタイプを他のタイプに変換したりするタイプ変換ルールをカスタマイズできます.このカスタムタイプ変換ルールは、クラスのメンバー関数としてのみ使用できます.すなわち、この変換ルールはクラスにのみ適用されます.このセクションでは、他のタイプを現在のクラスタイプに変換する方法について説明します.

  • 2.変換構造関数
  • 他のタイプを現在のクラスタイプに変換するには、変換コンストラクタ(Conversion constructor)を使用する必要があります.変換コンストラクション関数もコンストラクション関数であり、コンストラクション関数の一般的な規則に従い、変換コンストラクション関数には1つのパラメータしかありません.
        #include "iostream"
    
        using namespace std;
    
        /*---------------------------              -------------------------------*/
    
        //                  ,         
        class complex{
            public:
                complex():m_real(0.0), m_img(0.0){}
                complex(double real, double img):m_real(real), m_img(img){}
                complex(double real): m_real(real), m_img(0.0){}  //       ,    double     real    complex    ,  real       , 0       
            public:
                friend ostream & operator<< (ostream &out, const complex &c); //     
            private:
                double m_real;
                double m_img;
        };
    
        ostream & operator << (ostream &out, const complex &c){
            out << c.m_real << " + " << c.m_img << "i";
            return out;
        }
    
        int main(){
            complex a(10.0, 20.0);
            cout << "a = " << a << endl;
            a = 25.5;  //                  
            cout << "a = " << a << endl;
            return 0;
        }
    
  • 変換コンストラクション関数もコンストラクション関数の1つであり、他のタイプを現在のクラスタイプに変換するだけでなく、オブジェクトを初期化するためにも使用できます.これはコンストラクション関数の本来の意味です.次のオブジェクトの作成方法は正しいです:
        complex c1(23.1);  //       
        complex c2 = 24.3;  //            ,            , 24.3   complex  (    complex      ),      c2。
        complex(3.21);  //       
        c1 = complex(34.2);  //                c1
    
  • +演算子をリロードし、2つのcomplexクラスオブジェクトの加算が可能になった場合、次の文も正しい:
        complex c1(15.6, 89.9);
        complex c2;
        c2 = c1 + 29.6;
        cout << c2 << endl;
    
  • 注:ターゲット・タイプを取得するには、コンパイラは手段を選ばず、組み込みの変換ルールとユーザー定義の変換ルールを統合し、マルチレベル・タイプの変換を行います.たとえば、次のようにします.
  • コンパイラは、組み込みルールに基づいてintをdoubleに変換し、ユーザー定義ルールに基づいてdoubleをcomplexに変換します(int-->double-->complex).
  • コンパイラは、組み込みルールに従ってcharをintに変換し、intをdoubleに変換し、最後にユーザー定義ルールに従ってdoubleをcomplexに変換します(char-->int-->double-->complex)
        int main(){
            complex c1 = 100;  //int --> double --> complex
            cout << c1 << endl;
            c1 = 'A';  //char --> int --> double --> complex
            cout << c1 << endl;
            c1 = true;  //bool --> int --> double --> complex
            cout << c1 << endl;
            complex c2(25.8, 0.7);
            //       +   
            c1 = c2 + 'H' + true + 15;  // char、bool、int    complex     
            cout << c1 << endl;
            return 0;
        }
    

  • 3.コンストラクタについて
  • コンストラクション関数は、オブジェクトを作成するときにオブジェクトを初期化することを意味し、コンパイラは伝達された実パラメータに基づいて異なる(リロードされた)コンストラクション関数、いくつかの形式のコンストラクション関数をマッチングします.
  • デフォルトのコンストラクタ:コンパイラが自動的に生成するコンストラクタです.complexクラスを例にとると、そのプロトタイプは
        complex();  //    
    
  • です.
  • 一般的な構造関数:ユーザーがカスタマイズした構造関数であり、complexクラスを例にとると、その原型は:
        complex(double real, double img);  //     
    
  • である.
  • コピーコンストラクション関数:オブジェクトをコピーして初期化するときに呼び出され、complexクラスを例にとると、そのプロトタイプは
        complex(const complex &c);
    
  • である.
  • 変換コンストラクタ:他のタイプを現在のクラスタイプに変換するときに呼び出されます.complexを例にとると、そのプロトタイプは
        complex(double real);  //     
    
  • です.
  • は、いずれのコンストラクション関数もオブジェクトを初期化するために使用できます.これはコンストラクション関数の本意です.complexクラスが以上のすべてのコンストラクション関数を定義していると仮定すると、次のオブジェクトの作成方法は正しいです:
        complex c1();  //   complex()
        complex c2(10, 20);  //   complex(double real, double imag)
        complex c3(c2);  //   complex(const complex &c)
        complex c4(25.7);  //   complex(double real)
    
  • は、オブジェクトの作成時にオブジェクトを初期化するほか、コピーでオブジェクトを初期化するとコピーコンストラクタが呼び出され、他のタイプを現在のクラスタイプに変換すると変換コンストラクタが呼び出されます.これらの他の場合に呼び出されるコンストラクション関数は,特殊なコンストラクション関数となる.特殊な構造関数は必ずしも構造関数の本意を体現できるとは限らない.

  • 4.complexクラスのさらなる簡素化
  • 上のcomplexクラスでは、2つの一般的な構造関数と1つの変換構造関数を含む3つの構造関数を定義しました.実際には、関数のデフォルトパラメータを使用して、この3つの構造関数を1つに簡略化できます.次のコードを参照してください.
        #include "iostream"
    
        using namespace std;
    
        /*---------------------------              -------------------------------*/
    
        //                  ,         
        class complex{
            public:
                complex(double real=0.0, double img=0.0):m_real(real), m_img(img){}
            public:
                friend ostream & operator<< (ostream &out, const complex &c); //     
            private:
                double m_real;
                double m_img;
        };
    
        ostream & operator << (ostream &out, const complex &c){
            out << c.m_real << " + " << c.m_img << "i";
            return out;
        }
    
        int main(){
            complex a(10.0, 20.0);  //        2   ,       
            cout << "a = " << a << endl;
            complex b(89.5);  //        1   ,  1     
            cout << "b = " << b << endl;
            complex c;  //           ,        
            a = 25.5;  //         (       1   ,  1     )
            cout << "a = " << a << endl;
            return 0;
        }