C++中一些特殊函式的使用

gaopengtttt發表於2016-07-22
1、複製建構函式   有指標和引用屬性的應該使用深度複製 class_name(const class_name &);  
                  如:
charin::charin(charin &in)
{
        len = in.len;
        sin = new char[len];
    strcpy(sin,in.sin);
        num_s++;
        cout << len <<" bytes mem alloc!"<<endl;
        cout << sin <<" deep copy in "<<num_s<<endl;
}
2、等值複製函式   有指標和引用屬性的應該使用深度複製 如:
Stringbad & Stringbad::operator=(const Stringbad &st)
{
if(this == &st)
 return *this;
delete [] str;
len = st.len;
str = new char[len+1];
std::strcpy(str,st.str);
return *this;
}
3、隱士轉換函式 只有一個引數的建構函式會被用於隱士轉換。可以使用explicit來避免 如 class a,int b; a = b;  
4、強制轉換 如上:     class a,int b; b = a;  以及 int(a)等用到
   模型為operator typename()
    轉換函式必須是類方法
    轉換資料不能指定型別
    轉換函式不能有引數
    如:
    operator int() const; //declear in class
    operator doube() const;
    
    stonew::operator int() const
    {
    return int (pounds + 0.5);
    }
    stonew::operator double() const
    {
    return pounds;
    }
5、友元函式,某些不能轉換的操作
比如:
A=B*2.75
轉換為
A=B.operator*(2.75)
但是
A=2.75*B不能轉換需要用到友元函式

A=operator*(2.75,b)
原型為
class operator*(double m,const class & t)


友元函式用於訪問類中的私有資料,因為這部分是外部不能訪問,
友元能夠做到
注意:
友元函式必須在類中宣告,但是他不是成員函式,不需要使用成員運算子來呼叫   比如.和-> 不需要用什麼因為他的定義不使用::限定符
和成員函式訪問許可權相同,編寫函式定義不需要使用::限定符,定義使用friend
另外需要注意友元又有呼叫不使用任何成員方式如.和->包括::,所以其方法實現應該放到class定義以外


如:
friend Time operator*(double m,const class & t);
Time operator*(double m,const Time & t) //在之後定義不能在class中定義這樣就能找到方法
{
return t*m;
}

呼叫 直接 Time a=m*t;
這個呼叫會直接匹配到這個Time的有元函式
friend Time operator*(double m,const class & t)

6、構造
建構函式用於對物件的資料進行初始化,建構函式的和一般的方法(函式)有一些不同
他的名字必須是類的名字,不能帶返回值。一般來說即使你不建立建構函式,也會
為你建立預設的建構函式,但是預設的建構函式是什麼都不幹的。如:
stu::stu(void){}
7、析構
解構函式用於對物件的記憶體進行回收,(如用malloc和new分配的記憶體空間)解構函式在
物件消亡的時候會被自動呼叫,而不需要你手動呼叫,名稱為類名字前面加上~。一樣
解構函式不能帶返回值,並且解構函式沒有引數,同樣如果你設定解構函式,也會
為你預設建立解構函式,但是預設也是什麼都不做的。

8、建構函式列表
  當使用如下方式的時候需要使用建構函式列表初始化成員
  1、const 成員
  2、引用&成員
  3、繼承類的基類初始化
  4、本生就是類的成員


如:
class base
{
        private:
                char *name;
        public:
                base(const char* myname);
                base(const base & inc); //copy cons fun
                virtual ~base(void){delete [] name;cout<<"test"<<endl;};
                virtual int checkset(int cur_set);
};
class extrenl: public base
{
        private:
                const int id; //const
                int &id2;//引用
                string name; //物件類string 本生就是類
        public:
                extrenl(const int idi,const int &id2i,string names,base &inbase  ):id(idi),id2(id2i),name(names),base(inbase){} ; //init list
                extrenl(const char* myname,int mid);
                virtual ~extrenl(void){cout<<"teste"<<endl;};
                virtual int checkset(int cur_set);
};

其初始化順序和列表中無關是按照宣告的順序進行的

9、靜態static類成員函式
   特別之處
   1、宣告必須包含定義
   2、不包含THIS指標,在共有部分宣告的static函式,可以使用類名和域解析運算子呼叫如
      class test
      private:
      .....
      static int num_str
      public:
      ....
      static int show(){return num_str;}
      
      呼叫:
      int cont = test::show();
    也可以透過物件進行呼叫
    test a;
    a.show();
      3、不和特定的物件相關聯,只能訪問靜態資料成員,靜態成員是全類物件共享的。
          否則拋錯:
          報錯test.h:20:7: error: invalid use of member ‘tests::c’ in  static member function
          但是普通成員函式可以呼叫靜態資料成員(必須先初始化)。
    4、私有靜態成員函式只能由類方法自己呼叫而不能使用test::show()呼叫也不能用a.show();
      

 10、    靜態資料成員
      1、全部類物件共享一個靜態成員
      2、可以使用型別 類名和域解析運算子呼叫如 int test::num_str =0 進行賦值 
          公有static資料成員透過test::num_str訪問。
         注意: int test::num_str =0 宣告必須在宣告為全域性變數並且定義。
      3、也可以在類中直接訪問,但是不能建構函式中初始化。必須在宣告為全域性變數並且定義。
       4、私有static 資料成員也是用 int test::num_str =0 宣告必須在宣告為全域性變數並且定義。但是私有static成員資料只能透過類方法訪問
          test::num_str不能訪問。
報錯
testcc.cpp:61:5: error: ‘int testa::total’ is private
 int testa::total=1;
     ^
testcc.cpp:73:15: error: within this context
  cout<<testa::total<<endl;

      5、獨有的一塊靜態記憶體區域,解構函式無用
    !! 這應該是基於靜態資料必須在類初始化前進行初始化的考慮。
   !! 當然如果不斷的迴圈呼叫這個類建立物件靜態成員會不斷增大或者變化,和C靜態變數一樣。知道main程式執行結束

關於靜態函式和靜態資料成員繼承後使用的也是同一片區域,那麼也就是說靜態成員的基類和繼承類資料共享</testa::total<<endl;

          
9和10的例子:


點選(此處)摺疊或開啟

  1. #include
    using namespace std;


    class tests
    {
       private:
                    int c;
                    static int d;


                    static void adde(int int4)
                    {
                            d=d+int4;
                    }
       public:
                    //static int d;
                    static int a;
                    static void adda(int in1)
                    {
                            a+=in1;
                            //d=1; 不能定義
                            //a+=c;報錯test.h:20:7: error: invalid use of member ‘tests::c’ in static member function
                    }
                    tests(void){c=3;}
                    static int b;
                    static void addb(int in2)
                    {
                            b+=in2;
                    }
                    void addc(int int3)
                    {
                            c+=int3;
                            c+=a; //這裡呼叫了靜態資料成員a
                            cout<<c;
                            addb(a);//這裡直接呼叫了靜態函式成員
                    }
                    void addd(int int4)
                    {
                            d=d+int4;
                            addb(d);//呼叫靜態成員函式和靜態資料成員
                            adde(d);
                            cout<<d<<endl;
                    }
                    ~tests(){}
    };
    class testsp:public tests
    {
            private:
                    int m;
            public:
                    testsp(int in1):m(in1){}
    };

    </d<<endl;
    </c;

  2. #include
    #include"test.h"
    #include
    using namespace std;
    //所以私有成員資料必須宣告為全域性並且賦值
    int tests::a=1;//宣告和定義,static 成員函式比如這樣定義 
    int tests::b=2;
    int tests::d=5;//私有static成員d也可以這樣定義,但是函式不行
    //int testsp::d=50;繼承類繼承了tests::a=1;不能在宣告和定義並且是同一片記憶體區域


    int main(void)
    {
    //      int     tests::a=1; 這樣是不行的
             tests::adda(1);//直接透過域解析符號::訪問
             tests::addb(2);
    //       tests::adde(4);靜態不能訪問‘static int tests::adde(int)’ is private
            tests a;
            a.addc(1);
            a.adda(1);//透過物件訪問靜態成員函式
            cout<<endl;
            a.addd(5);
            cout<<tests::a<<endl;
            cout<<&tests::a<<endl;
            cout<<tests::b<<endl;
            testsp b(100);
            testsp::adda(1);
            cout<<testsp::a<<endl;
            cout<<&testsp::a<<endl;


            void (*p)(int)=testsp::adda;
            void (*p1)(int)=tests::adda;
            printf("%p\n",p1);
            printf("%p\n",p);
    }

    </endl;
    </testsp::a<<endl;
    </tests::b<<endl;
    </endl;
    </tests::a<<endl;
    </endl;

輸出為:
6
20
3
0x602088
16
4
0x602088
0x400bca
0x400bca

可以看到地址都是相同的



</endl;};
</endl;};
</num_s<<endl;
</endl;

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/7728585/viewspace-2122388/,如需轉載,請註明出處,否則將追究法律責任。

相關文章