包含:
http://www.cnblogs.com/uniqueliu/archive/2011/08/01/2124261.html
object.func().func2();
class A
{
//...
};
class B
{
//...
A a;
A b;
};
#include <iostream>
using namespace std;
class A
{
public:
A(int i){x=i;cout<<"調用A類的構造函數\n";}
~A(){cout<<"調用A類的析構函數\n";};
void get() {cout<<"A類中X的值爲:"<<x<<endl;}
private:
int x;
};
class B
{
public:
B(int i,int j,int k):a(i),b(j),y(k){cout<<"調用B類的構造函數\n";}
A geta(){return a;}
A getb(){return b;}
~B(){cout<<"調用B類的析構函數\n";}
void gety(){cout<<"B類中y的值爲:"<<y<<endl;}
private:
A a;
A b;
int y;
};
int main()
{
B b(1,2,3);
b.geta().get();
b.getb().get();
b.gety();
return 0;
}
友元類
如果某類B的成員函數會頻繁的存取另一個類A的數據成員, 而A的數據成員的Private/Protectd限製造成B存取的麻煩, B只能通過A的Public的成員函數進行間接存取
把B做成A類的友元類,即A類向B類開放其Private/Protectd內容, 讓B直接存取
友元類:一個類可以作另一個類的友元
友元類的所有成員函數都是另一個類的友元函數
友元類的聲明:
friend class 類名;
友元類注意事項:
1、友元關係是單向的
2、友元關係不能被傳遞
3、友元關係不能被繼承
4、有時候需要注意前向聲明
#ifndef _TELE_CONTROLLER_H_
#define _TELE_CONTROLLER_H_
class Television;
class TeleController
{
public:
void VolumeUp(Television &tv);
void VolumeDown(Television &tv);
void ChanelUp(Television &tv);
void ChanelDown(Television &tv);
};
#endif // _TELE_CONTROLLER_H_
#include "TeleController.h"
#include "Television.h"
void TeleController::VolumeUp(Television &tv)
{
tv.volume_ += 1;
}
void TeleController::VolumeDown(Television &tv)
{
tv.volume_ -= 1;
}
void TeleController::ChanelUp(Television &tv)
{
tv.chanel_ += 1;
}
void TeleController::ChanelDown(Television &tv)
{
tv.volume_ -= 1;
}
#ifndef _TELEVISION_H_
#define _TELEVISION_H_
class TeleController;
class Television
{
friend class TeleController;
public:
Television(int volume, int chanel);
private:
int volume_;
int chanel_;
};
#endif // _TELEVISION_H_
#include "Television.h"
Television::Television(int volume, int chanel) : volume_(volume), chanel_(chanel)
{
}
#include "Television.h"
#include "TeleController.h"
#include <iostream>
using namespace std;
int main(void)
{
Television tv(1, 1);
TeleController tc;
tc.VolumeUp(tv);
return 0;
}
嵌套類,局部類:
局部類
局部類是指在函數中定義類。
(c++不能在函數中定義函數。c++在類中定義的函數也就是成員函數。)這個類以及由它創建的對象,都侷限在該函數作用域中;必須在類內實現所有的成員函數,不能拿到類外。因爲函數是不可以嵌套定義的;若類內含有靜態數據成員,必須在該函數外初始化;類內不可含有靜態函數成員;類中不可使用包裹它的函數所定義的除靜態外的局部變量。
局部類
int a;
void fun()
{
static int s;
class A
{
public:
void init(int i) { s = i; }
};
A m;
m.init(10);
}
局部類的另一個用途是用來實現類型轉化
class Interface
{
public:
virtual void Fun() = 0;
};
template <class T, class P>
Interface* MakeAdapter(const T& obj, const P& arg)
{
int x;
class Local : public Interface
{
public:
Local(const T& obj, const P& arg)
: obj_(obj), arg_(arg) {}
virtual void Fun()
{
x = 100;
obj_.Call(arg_);
}
private:
T obj_;
P arg_;
};
return new Local(obj, arg);
}
.內嵌類
是在類體內定義的又一個類。外面的類叫外圍類。這個類以及由它創建的對象,都侷限在外層類作用域中;
外界能否使用內層類,全在於訪問權限;若能使用,定要以外圍類::內層類格式來用;
是類組合演化的又一種類間關係,即組合或聚集成員不是產生於其它類,而是產生於內層類;內層類的成員函數,可以在類內實現,也可以在外層類之外實現;
內層類的成員函數對外圍類的成員沒有訪問權,反之亦然
定義嵌套類的目的在於隱藏類名,減少全局的標識符,從而限制用戶能否使用該類建立對象。這樣可以提高類的抽象能力,並且強調了兩個類(外圍類和嵌套類)之間的主從關係。
class A
{
public:
class B
{
public:
…
private:
…
};
void f();
private:
int a;
}
其中,類B是一個嵌套類,類A是外圍類,類B定義在類A的類體內。
2 對嵌套類的若干說明:
1、從作用域的角度看,嵌套類被隱藏在外圍類之中,該類名只能在外圍類中使用。如果在外圍類的作用域內使用該類名時,需要加名字限定。
2、從訪問權限的角度來看,嵌套類名與它的外圍類的對象成員名具有相同的訪問權限規則。不能訪問嵌套類的對象中的私有成員函數,也不能對外圍類的私有部分中的嵌套類建立對象。
3、嵌套類中的成員函數可以在它的類體外定義。
4、嵌套類中說明的成員不是外圍類中對象的成員,反之亦然。嵌套類的成員函數對外圍類的成員沒有訪問權,反之亦然。國此,在分析嵌套類與外圍類的成員訪問關係時,往往把嵌套類看作非嵌套類來處理。
異常
abort
於一個用C++寫的程序,被加載至內存後運行,最終走向死亡。程序的死亡大致有三種:自然死亡,即無疾而終,通常就是main()中的一個return 0;自殺,當程序發現自己再活下去已經沒有任何意義時,通常會選擇自殺。當然,這種自殺也是一種請求式的自殺,即請求OS將自己斃掉。有兩種方式:void exit(int status)和void abort(void)。他殺,同現實不同的是,程序家族中的他殺行徑往往是由自己至親完成的,通常這個至親就是他的生身父親(還是母親?)。C++並沒有提供他殺的兇器,這些兇器往往是由OS直接或者間接(通過一些進程庫,如pthread)提供的。 自然死是最完美的結局,他殺是我們最不願意看到的,自殺雖是迫不得已,但主動權畢竟還是由程序自己掌控的;abort被調用時,程序將直接退出,任何對象的析構函數都不會調用
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <cstdlib>
using namespace std;
struct node {
double y;
node(){
cout<<"new"<<endl;
}
~node(){
cout<<"delete -- "<<y<<endl;
}
};
double hmean(node a, node b){
if(a.y == -b.y){
std::abort();
}
return 2.0*a.y*b.y/(a.y + b.y);
}
int main(){
node a, b, c;
while(scanf("%lf %lf", &a.y, &b.y)){
c.y = hmean(a, b);
printf("%lf\n",c.y);
}
return 0;
}
異常機制
對異常的處理有三個組成部分:
引發異常 捕獲處理程序的異常 使用try
#include <iostream>
#include <stdio.h>
#include <algorithm>
using namespace std;
double hmean(double a, double b);
int main(){
double x, y, z;
printf("Enter two numbers :");
while(scanf("%lf %lf", &x, &y) != EOF){
try{
z = hmean(x, y);
}
catch(const char *s){
printf("%s",s);
continue;
}
printf("%f %f", x, y);
printf(" %f \n",z);
}
printf("BYE\n");
return 0;
}
double hmean(double a, double b){
if(a == -b)
throw "bad hmean() arguments : a = -b not allowed";
return 2.0 * a * b/(a + b);
}
堆棧解退
當拋出了異常,但還沒在特定的作用域中被捕獲時,函數調用堆棧便被“解退”,並試圖在下一個外層try…catch代碼中捕獲這個異常。解退函數調用堆棧意味着拋出未捕獲異常的那個函數將終止,這個函數中的所有局部變量都將銷燬,控制會返回到原先調用這個函數的語句。
如果有一個try代碼塊包含了這條語句,則它就會試圖捕獲這個異常。如果沒有代碼塊包含這條語句,則堆棧解退再次發生。如果沒有任何catch處理器捕獲這個異常,則會調用terminate函數,終止程序。
下面的demo演示了堆棧解退:
#include <iostream>
#include <stdexcept>
using namespace std;
void fun3() throw (runtime_error)
{
cout<<"In fun 3"<<endl;
throw runtime_error("runtime_error in fun3");
}
void fun2() throw (runtime_error)
{
cout<<"fun3 is called inside fun2"<<endl;
fun3();
}
void fun1() throw (runtime_error)
{
cout<<"fun2 is called inside fun1"<<endl;
fun2();
}
int _tmain(int argc, _TCHAR* argv[])
{
try
{
cout<<"fun1 is called inside main"<<endl;
fun1();
}
catch(runtime_error &error)
{
cout<<"Exception occurred: "<< error.what()<<endl;
cout<<"exception handled in main"<<endl;
}
system("pause");
return 0;
}
運行結果:
注意:
程序運行堆棧解退以回到能夠捕捉異常的地方時,將釋放對戰中的自動存儲型變變量,如果變量是類對象, 將爲該對象調用析構函數
其他類異常特性
try-catch 跟 函數的區別:
函數調用返回時將控制權返回給調用其的函數, 而try-catch結構將控制權向上級返回。
exception類