C++ 學習(友元, 異常, 其他)

包含:
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類

發佈了448 篇原創文章 · 獲贊 3 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章