第9课 - 构造函数

第9课 - 构造函数

    一.对象的初始化

        1.1 对每个类都提供一个public的initialize函数

        对象创建后立即调用initialize函数进行初始化
          
 Source Example 1.1:
                #include <iostream>

                /* run this program using the console pauser or add your own getch, system("pause") or input loop */

                class Test {
                    private:
                        int i;
                    public:
                        void initialize()
                        {
                            i = 0;
                        }
                        
                        int geti()
                        {
                            return i;
                        }
                    
                };

                int main(int argc, char** argv) {
                    Test test1;
                    
                    test1.initialize();
                    
                    /* 输出结果为0 */
                    printf ("%d\n", test1.geti());
                            
                    return 0;
                }
        方案缺点:
            initialize只是一个普通的函数,必须显示的调用。
            一旦由于失误的原因,对象没有初始化,那么结果将是不确定的。

            

        1.2 C++中的构造函数

            1.2.1 C++中的类可以定义与类名相同的特殊成员函数

            1.2.2 这种类名相同的成员函数叫做构造函数

            1.2.3 构造函数在定义时可以有参数,但是没有任何返回类型的声明(与返回值为void完全不同)

            1.2.4 一般情况下C++编译器会自动调用构造函数,在一些情况下则需要手工调用

  
 Source Example 1.2:
                    #include <iostream>

                    /* run this program using the console pauser or add your own getch, system("pause") or input loop */

                    class Test {
                        private:
                            int i;
                            int j;
                            int k;
                        public:
                            Test (int v)        /* 构造函数 */
                            {
                                i = j = k = v;
                            }
                            
                            int print()
                            {
                                printf ("i = %d, j = %d, k = %d\n", i,j,k);
                            }
                        
                    };

                    int main(int argc, char** argv) {
                        Test test1(4);            /* 自动初始化 */
                        Test test2 = 5;            /* 自动初始化 */
                        Test test3 = Test(6);    /* 手动初始化 */
                        
                        /* 输出结果为:
                           i = 4,j = 5,k = 6
                           i = 4,j = 5,k = 6
                           i = 4,j = 5,k = 6 */
                        test1.print();
                        test2.print();
                        test3.print();
                        
                        /* 定义了类的对象数组,必须手动初始化,否则编译报错 */
                        Test tA[3] = {Test(1), Test(2),Test(3)};
                        
                        for (int i = 0; i < 3; i++)
                        {
                           /* 输出结果为:
                           i = 1,j = 2,k = 3
                           i = 1,j = 2,k = 3
                           i = 1,j = 2,k = 3 */
                            tA[i].print();
                        }    
                                
                        return 0;
                    }             

        1.3 成员函数的重载

            1.3.1 类的成员函数和普通函数一样可以重载,并遵守相同的重载规则

            1.3.2 构造函数也是成员函数,也可以进行重载

      
  Source Example 1.3:
            #include <iostream>

            /* run this program using the console pauser or add your own getch, system("pause") or input loop */

            class Test {
                private:
                    int i;
                    int j;
                    int k;
                public:
                    Test (int v)
                    {
                        i = j = k = v;
                    }
                    Test ()
                    {
                        i = 0;
                        j = 0;
                        k = 0;
                    }
                    
                    int print()
                    {
                        printf ("i = %d, j = %d, k = %d\n", i,j,k);
                    }
                    
                    int print(int v)
                    {
                        printf ("v = %d\n", v);
                    }
                
            };

            int main(int argc, char** argv) {
                /* 会调用一个参数的构造函数来初始化 */
                Test test1(4);
                Test test2 = 5;
                Test test3 = Test(6);
                Test test4;        /* 会调用没有参数的函数来初始化 */
                
                /* 输出结果为:
                   i = 4,j = 5,k = 6
                   i = 4,j = 5,k = 6
                   i = 4,j = 5,k = 6
                   i = 0,j = 0,k = 0 */
                test1.print();
                test2.print();
                test3.print();
                test4.print();
                
                /* 编译通过了,会调用没有参数的构造函数进行初始化 */
                Test tA[3];
                
                for (int i = 0; i < 3; i++)
                {
                    /* 输出结果为:
                       i = 0,j = 0,k = 0
                       i = 0,j = 0,k = 0
                       i = 0,j = 0,k = 0 */
                    tA[i].print();
                }
                        
                return 0;
            }

        1.4 两个特殊的构造函数

            1.4.1 拷贝构造函数(参数为const引用)

                当类中没有定义拷贝构造函数时,编译器默认提供一个拷贝构造函数,简单的进行成员变量的复制
                                

            1.4.2 默认构造函数(没有参数)

                当类中没有定义构造函数时,编译器默认提供一个无参构造函数,并且其函数体为空
                当自己写了任意一个构造函数之后,编译器就不会提供无参构造函数了
        
Source Example 1.4.1:
            #include <iostream>

            /* run this program using the console pauser or add your own getch, system("pause") or input loop */

            class Test {
                public:
                    
                    Test (const int& v)
                    {
                        printf ("const int& v!\n");
                    }
                    Test ()
                    {
                        printf ("no paramts!\n");
                    }
                    /* 当使用该函数时,编译不过,因为编译器就不会提供默认构造函数,Test t1;在定义时没有提供初始化参数,就会出错
                    Test (int v)
                    {
                        
                    }
                    */     
            };

            int main(int argc, char** argv) {
                
                /* 输出结果为
                    no paramts!
                    const int& v! */
                Test t1;
                Test t2 = 5;
                
                return 0;
            }
            注意:
                1.当类中没有定义任何一个构造函数,C++编译器会为我们提供无参构造函数和拷贝构造函数
                2.当类中定义了任意非拷贝构造函数时,C++编译器就不会为我们提供无参构造函数

                
      
 Source Example 1.4.2:
            #include <iostream>

            /* run this program using the console pauser or add your own getch, system("pause") or input loop */

            class Test {
                private:
                    int i;
                    int j;
                    int k;
                public:
                    void print()
                    {
                        printf("i = %d, j = %d, k = %d\n", i, j , k);
                    }
                
            };

            int main(int argc, char** argv) {
                
                Test t1;
                Test t2 = t1;  /* 会调用拷贝构造函数将t1成员变量的值拷贝给t2的成员变量 */
                
                /* 输出结果为:
                   i = 2031646, j = 0, k = 1
                   i = 2031646, j = 0, k = 1*/
                t1.print();
                t2.print();
                
                return 0;
            }     

    二.数组类的创建

      
  Source Example 2:
        /* array.h */
            #ifndef _ARRAY_H_
            #define _ARRAY_H_

            class Array{
                private:
                    int iLength;
                    int *pSpace;
                public:
                    Array(int length);
                    int getLength();
                    void setData(int index, int data);
                    int getData(int index);
                    int destroy();
            };

            #endif /* _ARRAY_H_ */
        
        /* array.c */
        #include "array.h"

        Array :: Array(int length)
        {
            iLength = length;
            if (length > 0)
            {
                pSpace = new int[length];
            }
        }

        int Array :: getLength()
        {
            return iLength;
        }

        void Array :: setData(int index, int data)
        {
            pSpace[index] = data;
        }

        int Array :: getData(int index)
        {
            return pSpace[index];
        }
    
        /* 自己提供的拷贝构造函数,具体原因见下列代码注释 */
        Array :: Array(const Array& obj)
        {
            iLength = obj.iLength;
            pSpace = new int[iLength];
            
            for (int i = 0; i < iLength; i++)
            {
                pSpace[i] = obj.pSpace[i];
            }
        }
        
        int Array :: destroy()
        {
            length = -1;    
            delete[] pSpace;
        }
        
        #include <iostream>
        #include "array.h"
        /* run this program using the console pauser or add your own getch, system("pause") or input loop */

        int main(int argc, char** argv) {
            
            Array a(10);
            
            for (int i = 0; i < 10; i++)
            {
                a.setData(i, i);
            }
            
            for (int j = 0; j < a.getLength(); j++)
            {
                printf ("%d\n", a.getData(j));
            }
            
            /* 通过构造函数将a的成员变量全部赋值给a2 */
            /* 包括iLength,pSpace指向了同一片空间 */
            Array a2 = a;        
            for (int j = 0; j < a2.getLength(); j++)
            {
                printf ("%d\n", a2.getData(j));
            }
            
            /* 释放空间的时候只能调用一个销毁函数,否则就会出错,解决方法就是自己提供一个拷贝构造函数 */
            a.destroy();
            a2.destroy();
            
            return 0;
      

    三.小结

        3.1 构造函数是C++里面用于初始化对象的特殊函数

        3.2 构造函数在对象创建时自动被调用

        3.3 构造函数和普通成员函数都遵循重载规则

        3.4 拷贝构造函数时对象正确初始化的重要保障

   
阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页