国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
靜態(tài)數(shù)據(jù)成員和靜態(tài)函數(shù)成員
static關(guān)鍵字至少有下列n個(gè)作用:
 ?。?)函數(shù)體內(nèi)static變量的作用范圍為該函數(shù)體,不同于auto變量,該變量的內(nèi)存只被分配一次,因此其值在下次調(diào)用時(shí)仍維持上次的值;
 ?。?)在模塊內(nèi)的static全局變量可以被模塊內(nèi)所用函數(shù)訪問,但不能被模塊外其它函數(shù)訪問;
  (3)在模塊內(nèi)的static函數(shù)只可被這一模塊內(nèi)的其它函數(shù)調(diào)用,這個(gè)函數(shù)的使用范圍被限制在聲明它的模塊內(nèi);
 ?。?)在類中的static成員變量屬于整個(gè)類所擁有,對(duì)類的所有對(duì)象只有一份拷貝;
 ?。?)在類中的static成員函數(shù)屬于整個(gè)類所擁有,這個(gè)函數(shù)不接收this指針,因而只能訪問類的static成員變量。

#include "iostream"
using namespace std;
int i = 1;
void other()
{
static int a = 2;
static int b;
int c = 10;
a = a + 2;
i = i + 32;
c = c + 5;
cout<<"---Other---"<<endl;
cout<<"i: "<<i<<" a: "<<a<<" b: "<<b<<" c: "<<c<<endl;
b = a;
}

void main()
{
static int a; //靜態(tài)整數(shù)默認(rèn)為0;
int b = -10;
int c =0;
cout<<"---Main---"<<endl;
cout<<"i: "<<i<<" a: "<<a<<" b: "<<b<<" c: "<<c<<endl;  // i = 1 ; a = 0 ; b = -10; c = 0;
c = c + 8;
other();
(2)// i = 33 ; a = 4 ; b = 0; c = 15;
cout<<"---Main---"<<endl;
cout<<"i: "<<i<<" a: "<<a<<" b: "<<b<<" c: "<<c<<endl;
(3)// i = 33 ; a = 0 ; b = -10; c = 8;
i = i + 10;
other();
(4)// i = 75 ; a = 6 ; b = 4; c = 15;
}


什么叫做靜態(tài)數(shù)據(jù)成員?它有何特點(diǎn)?

解:
類的靜態(tài)數(shù)據(jù)成員是類的數(shù)據(jù)成員的一種特例,采用static關(guān)鍵字來聲明。對(duì)于類的普通數(shù)據(jù)成員,每一個(gè)類的對(duì)象都擁有一個(gè)拷貝,就是說每個(gè)對(duì)象的同名數(shù)據(jù)成員可以分別存儲(chǔ)不同的數(shù)值,這也是保證對(duì)象擁有自身區(qū)別于其它對(duì)象的特征的需要,但是靜態(tài)數(shù)據(jù)成員,每個(gè)類只要一個(gè)拷貝,由所有該類的對(duì)象共同維護(hù)和使用,這個(gè)共同維護(hù)、使用也就實(shí)現(xiàn)了同一類的不同對(duì)象之間的數(shù)據(jù)共享。靜態(tài)數(shù)據(jù)成員可以被非靜態(tài)成員函數(shù)調(diào)用,(外部)引用靜態(tài)數(shù)據(jù)成員時(shí),使用<類名>::<靜態(tài)成員名>這種格式。

什么叫做靜態(tài)函數(shù)成員?它有何特點(diǎn)?

解:
使用static關(guān)鍵字聲明的函數(shù)成員是靜態(tài)的,靜態(tài)函數(shù)成員屬于整個(gè)類,同一個(gè)類的所有對(duì)象共同維護(hù),為這些對(duì)象所共享。靜態(tài)函數(shù)成員具有以下兩個(gè)方面的好處,一是由于靜態(tài)成員函數(shù)只能直接訪問同一個(gè)類的靜態(tài)數(shù)據(jù)成員,可以保證不會(huì)對(duì)該類的其余數(shù)據(jù)成員造成負(fù)面影響;二是同一個(gè)類只維護(hù)一個(gè)靜態(tài)函數(shù)成員的拷貝,節(jié)約了系統(tǒng)的開銷,提高程序的運(yùn)行效率。

#include <iostream>
using namespace std;

class CSell
{
public:
  static void sell(int n, double price);
  static double getSum();
  static double getAvg();
private:
  static double sum;
  static double avg;
  static int nCounts;
};

double CSell::sum = 0; //銷貨總數(shù)
double CSell::avg = 0; //銷貨平均數(shù)
int CSell::nCounts = 0; //銷貨件數(shù)

void CSell::sell(int n, double price)
{
  nCounts += n;
  sum += n * price;
  avg = sum / nCounts;
}

double CSell::getAvg()
{
  return avg;
}

double CSell::getSum()
{
  return sum;
}


int main()
{
  CSell::sell(5, 23.5);
  CSell::sell(12, 24.56);
  CSell::sell(100, 21.5);

  cout<<CSell::getSum()<<endl;
  cout<<CSell::getAvg()<<endl;
return 0;
}


1、靜態(tài)數(shù)據(jù)成員在定義或說明時(shí)前面加關(guān)鍵字static。

2、靜態(tài)成員初始化與一般數(shù)據(jù)成員初始化不同。靜態(tài)數(shù)據(jù)成員初始化的格式如下:

<數(shù)據(jù)類型><類名>::<靜態(tài)數(shù)據(jù)成員名>=<值>

這表明:

(1) 初始化在類體外進(jìn)行,而前面不加static,以免與一般靜態(tài)變量或?qū)ο笙嗷煜?/div>

(2) 初始化時(shí)不加該成員的訪問權(quán)限控制符private,public等。

(3) 初始化時(shí)使用作用域運(yùn)算符來標(biāo)明它所屬類,因此,靜態(tài)數(shù)據(jù)成員是類的成員,而不是對(duì)象的成員。

3、靜態(tài)數(shù)據(jù)成員是靜態(tài)存儲(chǔ)的,它是靜態(tài)生存期,必須對(duì)它進(jìn)行初始化。

4、引用靜態(tài)數(shù)據(jù)成員時(shí),采用如下格式:

<類名>::<靜態(tài)成員名>

如果靜態(tài)數(shù)據(jù)成員的訪問權(quán)限允許的話(即public的成員),可在程序中,按上述格式來引用靜態(tài)數(shù)據(jù)成員。


靜態(tài)成員函數(shù)

靜態(tài)成員函數(shù)和靜態(tài)數(shù)據(jù)成員一樣,它們都屬于類的靜態(tài)成員,它們都不是對(duì)象成員。因此,對(duì)靜態(tài)成員的引用不需要用對(duì)象名。

在靜態(tài)成員函數(shù)的實(shí)現(xiàn)中不能直接引用類中說明的非靜態(tài)成員,可以引用類中說明的靜態(tài)成員。如果靜態(tài)成員函數(shù)中要引用非靜態(tài)成員時(shí),可通過對(duì)象來引用。


下面看一個(gè)例子:
#include <iostream.h>
class Point
{
public:
void output()
{

}
static void init()
{
 
};

void main( void )
{
Point pt;
pt.init();
pt.output(); 
}

這樣編譯是不會(huì)有任何錯(cuò)誤的。
下面這樣看
#include <iostream.h>
class Point
{
public:
void output()

}
static void init()
{
 
};

void main( void )
{
Point::output();
}

這樣編譯會(huì)處錯(cuò),錯(cuò)誤信息:illegal call of non-static member function,為什么?
因?yàn)樵跊]有實(shí)例化一個(gè)類的具體對(duì)象時(shí),類是沒有被分配內(nèi)存空間的。
好的再看看下面的例子:
#include <iostream.h>
class Point
{
public:
void output()
{
 
}
static void init()
{
 
};

void main( void )
{
Point::init();
}
這時(shí)編譯就不會(huì)有錯(cuò)誤,因?yàn)樵陬惖亩x時(shí),它靜態(tài)數(shù)據(jù)和成員函數(shù)就有了它的內(nèi)存區(qū),它不屬于類的任何一個(gè)具體對(duì)象。
好的再看看下面的例子:
#include <iostream.h>
class Point
{
public:
void output()

}
static void init()
    x = 0;
    y = 0;
}
private:
int x;
int y;
};

void main( void )
{
Point::init();
}
編譯出錯(cuò):
illegal reference to data member 'Point::x' in a static member function
illegal reference to data member 'Point::y' in a static member function
在一個(gè)靜態(tài)成員函數(shù)里錯(cuò)誤的引用了數(shù)據(jù)成員,
還是那個(gè)問題,靜態(tài)成員(函數(shù)),不屬于任何一個(gè)具體的對(duì)象,那么在類的具體對(duì)象聲明之前就已經(jīng)有了內(nèi)存區(qū),
而現(xiàn)在非靜態(tài)數(shù)據(jù)成員還沒有分配內(nèi)存空間,那么這里調(diào)用就錯(cuò)誤了,就好像沒有聲明一個(gè)變量卻提前使用它一樣。
也就是說在靜態(tài)成員函數(shù)中不能引用非靜態(tài)的成員變量。
好的再看看下面的例子:
#include <iostream.h>
class Point
{
public:
void output()
{
    x = 0;
    y = 0;
    init(); 
}
static void init()
{

}
private:
int x;
int y;
};

void main( void )
{
Point::init();
}
好的,這樣就不會(huì)有任何錯(cuò)誤。這最終還是一個(gè)內(nèi)存模型的問題,
任何變量在內(nèi)存中有了自己的空間后,在其他地方才能被調(diào)用,否則就會(huì)出錯(cuò)。
好的再看看下面的例子:
#include <iostream.h>
class Point
{
public:
void output()
{
 
}
static void init()
    x = 0;
    y = 0;
}
private:
static int x;
static int y;
};
void main( void )
{
Point::init();
}
編譯:
Linking...
test.obj : error LNK2001: unresolved external symbol "private: static int Point::y" 
test.obj : error LNK2001: unresolved external symbol "private: static int Point::x" 
Debug/Test.exe : fatal error LNK1120: 2 unresolved externals
執(zhí)行 link.exe 時(shí)出錯(cuò).
可以看到編譯沒有錯(cuò)誤,連接錯(cuò)誤,這又是為什么呢?
這是因?yàn)殪o態(tài)的成員變量要進(jìn)行初始化,可以這樣:
#include <iostream.h>
class Point
{
public:
void output()
{
 
}
static void init()
    x = 0;
    y = 0;
}
private:
static int x;
static int y;
};

int Point::x = 0;
int Point::y = 0;

void main( void )
{
Point::init();
}
在靜態(tài)成員數(shù)據(jù)變量初始化之后就不會(huì)出現(xiàn)編譯錯(cuò)誤了。
再看看下面的代碼:
#include <iostream.h>
class Point
{
public:
void output()
{
 
}
static void init()
    x = 0;
    y = 0;
}
private:
static int x;
static int y;
};

void main( void )
{

}
編譯沒有錯(cuò)誤,為什么?
即使他們沒有初始化,因?yàn)槲覀儧]有訪問x,y,所以編譯不會(huì)出錯(cuò)。 

C++會(huì)區(qū)分兩種類型的成員函數(shù):靜態(tài)成員函數(shù)和非靜態(tài)成員函數(shù)。這兩者之間的一個(gè)重大區(qū)別是,靜態(tài)成員函數(shù)不接受隱含的this自變量。所以,它就無法訪問自己類的非靜態(tài)成員。

在某些條件下,比如說在使用諸如pthread(它不支持類)此類的多線程庫時(shí),就必須使用靜態(tài)的成員函數(shù),因?yàn)槠涞刂吠珻語言函數(shù)的地址兼容。這種銅限制就迫使程序員要利用各種解決辦法才能夠從靜態(tài)成員函數(shù)訪問到非靜態(tài)數(shù)據(jù)成員。

第一個(gè)解決辦法是聲明類的所有數(shù)據(jù)成員都是靜態(tài)的。運(yùn)用這種方式的話,靜態(tài)的成員函數(shù)就能夠直接地訪問它們,例如:

class Singleton
{
public:
    static Singleton * instance();
private:
    Singleton * p;
    static Lock lock;
};

Singleton * Singleton::instance()
{
lock.getlock(); // fine, lock is static
if (!p)
    p=new Singleton;
lock.unlock();
return p;

這種解決方法不適用于需要使用非靜態(tài)數(shù)據(jù)成員的類。

訪問非靜態(tài)數(shù)據(jù)成員

將參照傳遞給需要考量的對(duì)象能夠讓靜態(tài)的成員函數(shù)訪問到對(duì)象的非靜態(tài)數(shù)據(jù):

class A
{
public:
    static void func(A & obj);
    intgetval() const; //non-static member function
private:
intval;
}; 

靜態(tài)成員函數(shù)func()會(huì)使用參照obj來訪問非靜態(tài)成員val。

voidA::func(A & obj)
{
    int n = obj.getval();

將一個(gè)參照或者指針作為靜態(tài)成員函數(shù)的自變量傳遞,就是在模仿自動(dòng)傳遞非靜態(tài)成員函數(shù)里this自變量這一行為。

很喜歡API函數(shù)的那種調(diào)用方法,不論在哪個(gè)類中只要用“::API函數(shù)”就可以調(diào)用了。合理利用靜態(tài)類型(static)可以實(shí)現(xiàn)與此相似的全局變量和全局函數(shù)。
靜態(tài)變量和靜態(tài)函數(shù)有如下性質(zhì):
若在一個(gè)類中用關(guān)鍵字static聲明數(shù)據(jù)成員,則這個(gè)數(shù)據(jù)成員就只存在一個(gè)拷貝,無論該類創(chuàng)建了多少個(gè)實(shí)例,它始終只存在一個(gè),即使該類的實(shí)例一個(gè)也沒創(chuàng)建,它也存在。
若在一個(gè)類中用關(guān)鍵字static聲明函數(shù),該函數(shù)可以用“
類名::函數(shù)名
”方式訪問,無需引用該類的實(shí)例,甚至這個(gè)類的實(shí)例可以不存在。
利用這個(gè)性質(zhì)實(shí)現(xiàn)的全局變量和函數(shù)使用起來很方便。
值得注意的是,全局變量和全局函數(shù)最好集中封裝,不要在文檔、視圖等類內(nèi)部定義,這樣用起來才有全局的感覺。
例:
1、添加一個(gè)沒有基類的新類,設(shè)類名起為CPublic,姑且稱之為公用類
單擊“Insert”菜單下的“New Class”命令,選擇“Class type”為“Generic Class”,在“Name”欄中填入類名“CPublic”,單擊“OK”,則新類建立完畢。
2、包含公用類的頭文件,使各個(gè)類都能訪問它
CPublic的頭文件應(yīng)包含在應(yīng)用程序類的頭文件中,這樣在其它類中引用CPublic類時(shí)就不需要再包含了。
Test.h:(應(yīng)用程序類頭文件)

#include "Public.h"        //包含公用類頭文件
class CTestApp : public CWinApp
{
    …………
};
3、在公用類中定義全局變量和全局函數(shù),均使用static修飾,靜態(tài)變量還必須在類外定義和初始化
Public.h:(公用類頭文件)

class CPublic
{
public:
    CPublic();
    virtual ~CPublic();
public:
    static int x;        //全局變量
    static int time;     //全局變量
    static int f(int y);     //全局函數(shù)
    …………
}
在公用類中對(duì)靜態(tài)變量進(jìn)行初始化和定義函數(shù)體:
Public.cpp:(公用類程序文件)

int CPublic::x = 0;   //初始化全局變量
int CPublic::time;    //定義全局變量
CPublic::CPublic()
{
}
CPublic::~CPublic()
{
}
int CPublic::f(int y)    //全局函數(shù),這里不要再加static
{
    y++;
    return y;
}
4、全局量的使用
使用變量:
CPublic::變量名

使用函數(shù):
CPublic::函數(shù)()
如在視圖的某函數(shù)中訪問變量x和函數(shù)f():
void CTestView::xyz()
{
    CPublic::x = 0;        //訪問變量x
    CPublic::time = CPublic::f(1);        //訪問函數(shù)f()
    …………
}
在其它類中訪問x、time和f()的方法與此相同。
5、幾點(diǎn)注意:
① 由于靜態(tài)量可獨(dú)立于類存在,
不需要生成CPublic類的實(shí)例
。
靜態(tài)數(shù)據(jù)成員的定義和初始化必須在類外進(jìn)行
,如例中x的初始化;變量time雖然沒有初始化,但也必須在類外進(jìn)行定義。由于沒有生成CPublic類的實(shí)例,所以它的構(gòu)造函數(shù)和析構(gòu)函數(shù)都不會(huì)被執(zhí)行,在里面做什么工作都沒有什么意義。
③ 如果靜態(tài)函數(shù)需要訪問CPublic類內(nèi)的變量,這些變量也必須為靜態(tài)的。因?yàn)榉庆o態(tài)量在不生成實(shí)例時(shí)都不會(huì)存在。
如:
class CPublic
{
public:
    int x;                //內(nèi)部變量
    static int f(int y)   //全局函數(shù)
    {
        x++;
        return x;
    };
    …………
};
這里x雖為類內(nèi)成員,但如果不生成CPublic類的實(shí)例,就會(huì)出現(xiàn)函數(shù)f()存在,而變量x不存在的問題。
總之,用沒有實(shí)例的類管理全局量是一個(gè)不錯(cuò)的選擇,它具有集中管理,使用方便的好處。當(dāng)然,除非特別必要,全局量還是少用為好,一個(gè)好的編程者決不會(huì)隨意濫用全局量的,一個(gè)封裝做得不好的程序,在修改維護(hù)時(shí)會(huì)讓你吃足苦頭。


靜態(tài)數(shù)據(jù)成員通常應(yīng)該通過非內(nèi)聯(lián)函數(shù)來訪問。
問題:
書上有一段話:如果要通過非靜態(tài)函數(shù)來訪問靜態(tài)數(shù)據(jù)成員,應(yīng)該使用非內(nèi)聯(lián)函數(shù)。同時(shí)我看到的程序如下:

#include <iostream> 
using namespace std; 
class Point 
public: 
Point(int xx=0,int yy=0) {X=xx;Y=yy;countP++;} Point(Point&p); 
~Point(){countP--;} 
int GetX(){return X;} 
int GetY(){return Y;} 
void GetC(){cout<<"Object id="<<countP<<endl;} 
private: 
int X,Y; 
static int countP; 
}; 

Point::Point(Point&p) 
X=p.X; 
Y=p.Y; 
countP++; 

int Point::countP=0; 
int main() 
Point A(4,5); 
cout<<"Point A,"<<A.GetX()<<","<<A.GetY(); 
A.GetC(); 
Point B(A); 
cout<<"Point B,"<<B.GetX()<<","<<B.GetY(); 
B.GetC(); 

void GetC(){cout<<"Object id="<<countP<<endl;} 中函數(shù)體直接放在類體內(nèi),是一種內(nèi)聯(lián)函數(shù)的隱式聲明,這不是和書上“該使用非內(nèi)聯(lián)函數(shù)”的意思矛盾了?

答:

書上原話:因?yàn)榫幾g器確保在調(diào)用任何一個(gè)非內(nèi)聯(lián)函數(shù)之前,會(huì)初始化靜態(tài)數(shù)據(jù)成員,但是因?yàn)檎{(diào)內(nèi)聯(lián)函數(shù)的時(shí)候,可能沒有初始化靜態(tài)數(shù)據(jù)成員,所以這樣操作(內(nèi)聯(lián)函數(shù)中調(diào)靜態(tài)數(shù)據(jù)成員)是不安全的。

這個(gè)Point::countP使用全局初始化的。
在編譯時(shí)候是在main運(yùn)行之前就已經(jīng)初始化了的。
所以即使寫在內(nèi)聯(lián)函數(shù)里面也沒關(guān)系。

另外,如果沒記錯(cuò)的話,書中寫的應(yīng)該是“最好通過非內(nèi)聯(lián)函數(shù)訪問”
之所以這么做的原因是為了避免內(nèi)聯(lián)成員在為初始化的時(shí)候就被使用了。

但是你看這段程序,全局初始化發(fā)生在main之前,
數(shù)據(jù)直接存儲(chǔ)在EXE的數(shù)據(jù)段了。
所以不會(huì)發(fā)生初始化之前的訪問的。

建議你用斷點(diǎn)看看程序運(yùn)行的順序就知道了。

但是這是針對(duì)這個(gè)程序合理,如果程序大了的話,其他編譯單元調(diào)用靜態(tài)但遠(yuǎn)遠(yuǎn)可能會(huì)發(fā)生對(duì)為初始化變量的訪問。
所以最好還是不要寫在內(nèi)聯(lián)函數(shù)中。


靜態(tài)成員函數(shù)可以直接訪問靜態(tài)數(shù)據(jù)和函數(shù)成員。而訪問非靜態(tài)數(shù)據(jù)成員必須通過參數(shù)傳遞方式得到對(duì)象名,然后通過對(duì)象名來訪問。
class A
{
public:
static void f (A a);
private:
int x;
};

void A::f(A a)
{
cout<<x; //錯(cuò)誤
cout<<a.x;//正確
}
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服