C++類的其他成員變數及屬性
一 靜態成員變數
1 把一個類的成員說明為 static 時,這個類無論有多少個物件被建立,
這些物件共享這個 static 成員.
2 靜態成員區域性於類,它不是物件成員
#include<iostream> using namespace std; class counter { static int num ; //宣告與定義靜態資料成員 public : void setnum ( int i ) { num = i ; } //成員函式訪問靜態資料成員 void shownum() { cout << num << '\t' ; } } ; int counter :: num = 0 ;//宣告與定義靜態資料成員 void main () { counter a , b ; a.shownum() ; //呼叫成員函式訪問私有靜態資料成員 b.shownum() ; a.setnum(10) ; a.shownum() ; b.shownum() ; }
二 靜態成員函式
1 靜態成員函式提供不依賴於類資料結構的共同操作,它沒有this指標
2 在類外呼叫靜態成員函式用 “類名 :: ”作限定詞,或通過物件呼叫。
3 靜態成員函式中,不能使用普通成員變數,不能使用普通成員函式。
靜態成員變數屬於整個類的,分不清楚,是那個具體物件的屬性。
#include <iostream> using namespace std; class BB { public: void printC() { cout<<"c:"<<c<<endl; } void AddC() { c = c + 1; } static void getC() //靜態成員函式 { cout<<"c:"<<c<<endl; //請在靜態成員函式中,能呼叫 普通成員屬性 或者 普通成員函式嗎? cout<<"a:"<<a<<endl; //error C2597: 對非靜態成員“BB::a”的非法引用 } private: int a; int b; static int c; //靜態成員變數 }; //靜態函式中 不能使用 普通成員變數 普通成員函式 .. int BB::c = 10; void main() { BB b1, b2, b3; b1.printC(); //10 b2.AddC(); //11 b3.printC(); //11 //靜態成員函式的呼叫方法 b3.getC(); //用物件. BB::getC();//類:: cout<<"hello..."<<endl; system("pause"); return ; }
三 C++面向物件模型初探
1 在c語言中,“資料”和“處理資料的操作(函式)”是分開來宣告的,也就是說,語言本身並沒有支援“資料和函式”之間的關聯性。
在c++中,通過抽象資料型別(abstract data type,ADT),在類中定義資料和函式,來實現資料和函式直接的繫結。
2 在C++類中有兩種成員資料:static、nonstatic;
三種成員函式:static、nonstatic、virtual。
3 總結
1)C++類物件中的成員變數和成員函式是分開儲存的。C語言中的記憶體四區模型仍然有效!
2)C++中類的普通成員函式都隱式包含一個指向當前物件的this指標;
3) 靜態成員函式、成員變數屬於類
4 )靜態成員函式不包含指向具體物件的指標
#include <iostream>
using namespace std;
class Test
{
public:
Test(int a, int b) //---> Test(Test *this, int a, int b)
{
this->a = a;
this-> b = b;
}
void printT()
{
cout<<"a: " <<a <<endl;
cout<< "b: " << this->b <<endl;
}
//1 const 寫的什麼位置 沒有關係
//2 const修飾的是誰?
// 2-1const修飾的是形參a 不是
// 2-2const修飾的是屬性this->a this->b
// 2-3 const修飾的是this指標所指向的記憶體空間, 修飾的是this指標
void OpVar( int a, int b) const //==>void OpVar(const Test *this, int a, int b)
//==>void OpVar( const Test *const this, int a, int b)
{
a = 100;
//this->a = 100;
//this->b = 200;
//this = 0x11;
//cout<<"a: " <<a <<endl;
cout<< "b: " << this->b <<endl;
}
private:
int a;
int b;
};
void main()
{
int *m_space = new int[0];
if (m_space == NULL)
{
return ;
}
Test t1(1, 2);
t1.printT();// ===> printT(&t1)
cout<<"hello..."<<endl;
system("pause");
return ;
}
四 全域性函式與成員函式
1 把全域性函式轉化成成員函式,通過this指標隱藏左運算元
Test add(Test &t1, Test &t2)===》Test add(Test &t2)
2 把成員函式轉換成全域性函式,多了一個引數
void printAB()===》void printAB(Test *pthis)
五 友元
1 友元函式
1)友元函式不是類的成員函式,是類的“好朋友”,可以修改類的私有屬性。
2)特點:
a) 一般友元函式要的引數要包含是哪個類的物件指標或物件引用。
b) 友員類通常設計為一種對資料操作或類之間傳遞訊息的輔助類。
2 友元類
1)若B類是A類的友員類,則B類的所有成員函式都是A類的友員函式;
2)友員類通常設計為一種對資料操作或類之間傳遞訊息的輔助類 ;
#include <iostream>
using namespace std;
class A
{
public:
friend class B;//B類 是 A的好朋友 ,在B中可以訪問A類的私有成員 私有函式
//1 宣告的位置 和 public private沒有關係
friend void modifyA(A *pA, int _a); //2 函式modifyA 是 類A的好朋友
A(int a=0, int b=0)
{
this->a = a;
this->b = b;
}
int getA()
{
return this->a;
}
private:
int a;
int b;
};
void modifyA(A *pA, int _a)
{
//pA->a = 100;
pA->a = _a;
class B
{
public:
void Set(int a)
{
Aobject.a = a;
}
void printB()
{
cout<<Aobject.a <<endl;
}
private:
A Aobject;
};
void main()
{
B b1;
b1.Set(300);
b1.printB();
system("pause");
}
void main2101()
{
A a1(1, 2);
cout<< a1.getA()<<endl;
modifyA(&a1, 300);
cout<< a1.getA()<<endl;
cout<<"hello..."<<endl;
system("pause");
return ;
}
六 運算子過載
1 運算子過載的本質是函式呼叫
2運算子過載的限制:a)不改變運算子的優先順序b)不改變運算子的結核性c)不改變運算子需要的運算元d)不創造新的運算子
3 運算子過載程式設計基礎
a)運算子函式是一種特殊的成員函式或友元函式
b)成員函式的語法形式:
型別 類名 ::operator op(引數){}
4全域性函式、類成員函式方法實現運算子過載步驟
1)要承認操作符過載是一個函式,寫出函式名稱
2)根據運算元,寫出函式引數
3)根據業務,完善函式返回值(看函式是返回引用 還是指標 元素),及實現函式業務
#include <iostream>
using namespace std;
class Complex
{
private:
int a;
int b;
//全域性函式 過載+運算子
friend Complex operator+(Complex &c1, Complex &c2);
//過載 前置++
friend Complex& operator++(Complex &c1);
//後置++
friend Complex operator++(Complex &c1, int);//int是佔位符。主要是實現引數過載
public:
Complex(int a=0, int b=0)
{
this->a = a;
this->b = b;
}
void printCom()
{
cout<<a<<" + " << b << "i" <<endl;
}
public:
//成員函式法 實現 -運算子過載
Complex operator-(Complex &c2)
{
Complex tmp(this->a - c2.a, this->b - c2.b);
return tmp;
}
//前置--
Complex& operator--()
{
this->a --;
this->b --;
return *this;
}
//後置--
Complex operator--(int)
{
Complex tmp = *this;
this->a--;
this->b--;
return tmp;
}
};
//全域性函式法 實現 + 運算子過載
Complex operator+(Complex &c1, Complex &c2)
{
Complex tmp(c1.a + c2.a, c1.b + c2.b);//生成匿名物件
return tmp;
}
//前置++
Complex& operator++(Complex &c1)
{
c1.a++;
c1.b++;
return c1;
}
//後置++
Complex operator++(Complex &c1, int)
{
//先使用 在讓c1加加
Complex tmp = c1;
//return c1;
c1.a ++;
c1.b ++;
return tmp;
}
void main()
{
Complex c1(1, 2), c2(3, 4);
//1 全域性函式法 實現 + 運算子過載
// Complex operator+(Complex &c1, Complex &c2);
Complex c3 = c1 + c2;
c3.printCom();
//2 成員函式法 實現 -運算子過載
//如果是成員函式則呼叫形式如:c1.operator-(c2);//
//Complex operator-(Complex &c2)
Complex c4 = c1 - c2;
c4.printCom();
//前置++操作符 用全域性函式實現
++c1;
c1.printCom();
//前置--操作符 成員函式方法
--c1;
c1.printCom();
//Complex& operator++(Complex &c1)
//c1.operator--();
//後置++操作符 用全域性函式實現
c1++;
c1.printCom();
//後置--操作符 用成員函式實現
c1--;
c1.printCom();
//c1.operator--()
cout<<"hello..."<<endl;
system("pause");
return ;
}