C++中一些特殊函式的使用
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的例子:
輸出為:
6
20
3
0x602088
16
4
0x602088
0x400bca
0x400bca
可以看到地址都是相同的
</endl;};
</endl;};
</num_s<<endl;
</endl;
如:
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的例子:
點選(此處)摺疊或開啟
-
#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;
-
-
#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/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- C++中compare函式的使用C++函式
- CSS中position樣式的一些特殊用法CSS
- C++中的strrev函式C++函式
- C++ 中特殊的用法C++
- C++特殊成員函式及其生成機制C++函式
- C++中strlen函式C++函式
- C++中函式呼叫的用法C++函式
- C++中的函式簽名C++函式
- C++ 中的虛擬函式C++函式
- C++中的回撥函式C++函式
- js中函式的一些”坑“JS函式
- C++中函式指標與函式物件C++函式指標物件
- c++中訊息函式 -- GetMessage函式C++函式
- C/C++—— C++中函式重寫和函式過載C++函式
- C++中的函式指標和函式物件總結C++函式指標物件
- [cpp]C++中的解構函式C++函式
- C++ functional庫中的仿函式C++Function函式
- C++中虛擬函式的作用C++函式
- 談談C++中的swap函式C++函式
- c++中內建函式C++函式
- c++一些常見的內建函式(字串)C++函式字串
- C++回撥函式(callback)的使用C++函式
- C/C++—— C++中建構函式不能是虛擬函式的原因分析C++函式
- 函式指標使用c++類成員函式函式指標C++
- C++中的虛擬函式與虛擬函式表 (轉)C++函式
- C++函式中那些不可以被宣告為虛擬函式的函式C++函式
- Python 擴充之特殊函式(lambda 函式,map 函式,filter 函式,reduce 函式)Python函式Filter
- C++中push_back()函式的用法C++函式
- C++中的虛擬函式(virtual function)C++函式Function
- 關於C++當中的“模板函式”C++函式
- 關於 JavaScript 中的特殊函式,你應該這樣看JavaScript函式
- 三角函式影像問題中特殊的任意與存在函式
- C++的函式式革命C++函式
- Python中,類的特殊方法與內建函式的關聯Python函式
- C++的函式和模板函式 (轉)C++函式
- Angular 14 inject 函式使用過程中的一些注意事項Angular函式
- C++中建構函式,拷貝建構函式和賦值函式的詳解C++函式賦值
- python 中的一些特殊語法Python