注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

又一个部落格

换过很多备忘录,不知道这本怎么样!

 
 
 

日志

 
 

异常, 模板, 命名空间等  

2010-03-05 15:15:43|  分类: c++ |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
异常处理
3个关键字
try,catch,throw

#include <iostream>
using namespace std;

int main(int argc,char *argv[]) {
    cout<<"start\n";

    try{
        cout<<"Inside try block\n";
        throw 99;
        //下面一句将不会执行
        cout <<"This will not execute";
    }
    // 类型要对应,否则异常将不会执行,会发生运行时错误
    catch(int i){
        cout<<"Caught an exception --value is:";
        cout<<i<<endl;
    }
    cout <<"end";

    return 0;
}

使用多个catch块
#include <iostream>
using namespace std;

void Xhandler(int test){
    try{
        if(test)
            throw test;
        else
            throw "string"; //这个地方,不同的编译器会出现不同情况,具体还不怎么明白,vs是可以的
    }
    catch(int i){
        cout<<"Caught One! Ex. #:" << i << endl;
    }
    catch(char *str){
        cout <<"Caught a string: "<< str << endl;
    }
}

int main() {
    cout<<"start\n";
    Xhandler(1);
    Xhandler(2);
    Xhandler(0);
    Xhandler(3);

    cout <<"end";

    return 0;
}

当抛出异常类型是 class 的时候要注意 catch块 派生类和基类的次序/
因为基类可以匹配派生类.所以一般把基类放到派生类后面. 看下面的程序.
#include <iostream>
using namespace std;

class B{};
class D:public B{};

int main() {
    D derived;
    try{
        throw derived;
    }
    catch(B d){
            cout << "Caught a base class.\n";
        }
    //假如怎样写,那么这个catch块将永远没有机会执行
    catch(D d){
        cout << "This won't execute.\n";
    }

    return 0;
}

捕捉所有的类型异常
#include <iostream>
using namespace std;

void Xhandler(int test){
    try{
        if(test==0)throw test;
        if(test==1)throw 'a';
        if(test==2)throw 123.23;
    }
    // ... 表示匹配是所有类型
    catch(...){
        cout << "Caught One!\n";
    }
}
int main() {
    cout<<"start\n";
    Xhandler(0);
    Xhandler(1);
    Xhandler(2);
    cout<<"end\n";
    return 0;
}

指定函数只能抛出那种类型的异常
ret-type func-name(arg-list) throw(type-list) { // ... }
#include <iostream>
using namespace std;

void Xhandler(int test)throw (int,char,double){
        if(test==0)throw test;
        if(test==1)throw 'a';
        if(test==2)throw 123.23;
}
int main() {
    cout<<"start\n";
    try{
    Xhandler(0);
    Xhandler(1);
    Xhandler(2);
    cout<<"end\n";
    }
    catch(...){
        cout << "Caught One!\n";
    }
    return 0;
}

重新抛出异常
这个是在嵌套的 try中才会出现的.
假如内层的try捕捉到一个异常,想让外层的来处理,那么在 catch块中再次抛出.
#include <iostream>
using namespace std;

void Xhandler(){
    try{
        throw 1;
        //注意这个地方 可以没有变量名称,只有变量类型
    }catch(int){
        cout << "Caught int inside Xhandler\n";
        throw;
    }
}
int main() {
    cout<<"start\n";
    try{
        Xhandler();
    }
    catch(int){
        cout << "Caught int inside main\n";
    }
    cout<<"end\n";
    return 0;
}


模板
通用函数,模板函数
template <class Ttype> ret-type func-name(parameter list) { // body of function }
Ttype是一个数据类型的占位符的名称
看下面的例子
#include <iostream>
using namespace std;

template <class X> void swapargs(X &a,X &b){
    X temp;
    temp =a;
    a=b;
    b=temp;
}
int main() {
    int i=10,j=20;
    float x=10.1,y=23.3;
    char a='x',b='z';

    cout <<"Original i , j:"<<i<<' '<< j<<endl;
    cout <<"Original x , y:"<<x<<' '<< y<<endl;
    cout <<"Original a , b:"<<a<<' '<< b<<endl;

    swapargs(i,j);
    swapargs(x,y);
    swapargs(a,b);

    cout<<"Swapped i,j: "<<i<<' '<< j<<endl;
    cout<<"Swapped x,y: "<<x<<' '<< y<<endl;
    cout<<"Swapped a,b: "<<a<<' '<< b<<endl;
    return 0;
}

实际上,编译器会应该是动态自动的产生3个版本的swapargs函数

多个占位符
#include <iostream>
using namespace std;

template <class Type1, class Type2> void myfunc(Type1 x,Type2 y){
    cout<<x<<' '<<y<<endl;
}
int main() {
    myfunc(10, "hi");
    myfunc(0.23, 10L);
    return 0;
}

模板函数的重载
#include <iostream>
using namespace std;

template <class X> void swapargs(X &a,X &b){
    X temp;
    temp =a;
    a=b;
    b=temp;
    cout<<"Inside template swapargs.\n";
}

//重载 swapargs 模板函数
void swapargs(int &a, int &b){
    int temp;

    temp=a;
    b=temp;
    cout<<"Inside swapargs int specialization.\n";
}
int main() {
    int i=10,j=20;
    float x=10.1,y=23.3;
    char a='x',b='z';

    cout <<"Original i , j:"<<i<<' '<< j<<endl;
    cout <<"Original x , y:"<<x<<' '<< y<<endl;
    cout <<"Original a , b:"<<a<<' '<< b<<endl;

    // 这里调用了重载的 int版本的 函数 swapargs
    swapargs(i,j);
    swapargs(x,y);
    swapargs(a,b);

    cout<<"Swapped i,j: "<<i<<' '<< j<<endl;
    cout<<"Swapped x,y: "<<x<<' '<< y<<endl;
    cout<<"Swapped a,b: "<<a<<' '<< b<<endl;
    return 0;
}

上面的重载还有另外的一种更加专业化的写法
怎样写的好处是 一看就知道重载的是一种模板
template<> void swapargs <int>(int &a,int &b){
    int temp;
    temp=a;
    b=temp;
    cout<<"Inside swapargs int specialization.\n";
}

模板类
template <class Ttype> class class-name {
// body of class }
Ttype是占位符类型
创建一个特殊类型模板类的对象
class-name <type> ob;
看例子
#include <iostream>
using namespace std;

template <class T> class MyClass{
    T x,y;
public:
    MyClass (T a, T b){
        x=a;
        y=b;
    }
    T div(){return x/y;}
};


int main() {
    //创建double类型的对象
    MyClass<double> d_ob(10.0, 3.0);
    cout<<"double division: " << d_ob.div()<<endl;
    //创建int类型的对象
    MyClass<int>i_ob(10,3);
    cout<<"integer divison: "<<i_ob.div()<<endl;
    return 0;
}

定义多个类型的模板类
#include <iostream>
using namespace std;

template <class T1,class T2> class MyClass{
    T1 i;
    T2 j;
public:
    MyClass (T1 a, T2 b){
        i=a;
        j=b;
    }
    void show(){cout<<i<<' '<<j<<endl;}
};


int main() {
    MyClass<int, double> ob1(10, 0.23);
    MyClass<char,char *>ob2('X',"This is a test");
    ob1.show();
    ob2.show();
    return 0;
}

重载模板类
#include <iostream>
using namespace std;

template <class T> class MyClass{
    T x;
public:
    MyClass (T a){
        x=a;
    }
    T getx(){return x;}
};

//创建一个特殊的 int版本的
template <> class MyClass<int>{
    int x;
public:
    MyClass(int a){
        cout<<"Inside MyClass<int> specialization"<<endl;
        x=a*a;
    }
    int getx(){return x;}
};

int main() {
    MyClass<double> d(10.1);
    cout<<"double: "<<d.getx()<<endl<<endl;

    MyClass<int> i(5);
    cout<<"int: "<<i.getx()<<endl;
    return 0;
}

动态分配
两个运算符
new delete
值得注意的地方时,如果 用delete删除没有用new分配的变量,会导致严重问题,比如系统崩溃
new出来的变量都是指针类型的

#include <iostream>
#include <new>
using namespace std;

int main() {
    int *p;
    try{
        p = new int;
    }catch(bad_alloc xa){
        cout<<"Allocation Failure"<<endl;
        return 1;
    }
    *p =100;
    cout<<"At "<<p<<" ";
    cout<<"is the value "<<*p<<endl;
    delete p;
    return 0;
}

也可以初始化
#include <iostream>
#include <new>
using namespace std;

int main() {
    int *p;
    try{
    //初始化
        p = new int(87);
    }catch(bad_alloc xa){
        cout<<"Allocation Failure"<<endl;
                return 1;
    }

    cout<<"At "<<p<<" ";
    cout<<"is the value "<<*p<<endl;
    delete p;
    return 0;
}

分配数组
delete [ ] p_var;


#include <iostream>
#include <new>
using namespace std;

int main() {
    int *p, i;
    try{
    //申请动态分配数组
        p = new int[10];
    }catch(bad_alloc xa){
        cout<<"Allocation Failure"<<endl;
        return 1;
    }
    for(i=0;i<10;i++)
        p[i] = i;

    for(i=0;i<10;i++)
        cout << p[i]<<" ";
    //删除动态分配的数组
    delete []p;
    return 0;
}


分配对象
值得注意的是,动态分配的对象返回的是一个指针.
#include <iostream>
#include <new>
using namespace std;

class Rectangle{
    int width;
    int height;
public:
    Rectangle(int w,int h){
        width =w;
        height = h;
        cout<<"Constructing "<<width<<" by "<<height <<" rectangle.\n";
    }
    ~Rectangle(){
        cout<<"Destructing "<<width<<" by "<< height<<" rectangle.\n";
    }
    int area(){
        return width * height;
    }
};

int main() {
    //new以后是一个指针
    Rectangle *p;
    try{
        p = new Rectangle(10,8);;
    }catch(bad_alloc xa){
        cout<<"Allocation Failure"<<endl;
        return 1;
    }
    cout<<"Area is "<<p->area();
    cout<<"\n";

    delete p;
    return 0;
}


当用new操作符定义类数组时候,必须确保类的构造函数是没有参数的,不然无法编译.
不是用new的是可以的


命名空间
#include <iostream>
using namespace std;

namespace CounterNameSpace{
    int upperbound;
    int lowerbound;
    class counter{
        int count;
    public:
        counter(int n){
            if(n<=upperbound)
                count =n;
            else
                count = upperbound;
        }
        void reset(int n){
            if(n<=upperbound)count=n;
        }
        int run(){
            if(count>lowerbound)
                return count--;
            else
                return lowerbound;
        }
    };
}

int main() {
    CounterNameSpace::upperbound = 100;
    CounterNameSpace::lowerbound = 0;

    CounterNameSpace::counter ob1(10);

    int i;

    do{
        i=ob1.run();
        cout<<i<<" ";
    }while(i>CounterNameSpace::lowerbound);
    cout <<endl;

    CounterNameSpace::counter ob2(20);
    do{
        i=ob2.run();
        cout<<i<<" ";
    }while(i>CounterNameSpace::lowerbound);
    cout<<endl;

    ob2.reset(100);
    CounterNameSpace::lowerbound = 90;
    do{
        i=ob2.run();
        cout<<i<<" ";
    }while(i>CounterNameSpace::lowerbound);

    return 0;
}

也可以这样子写
#include <iostream>
using namespace std;

namespace CounterNameSpace{
    int upperbound;
    int lowerbound;
    class counter{
        int count;
    public:
        counter(int n){
            if(n<=upperbound)
                count =n;
            else
                count = upperbound;
        }
        void reset(int n){
            if(n<=upperbound)count=n;
        }
        int run(){
            if(count>lowerbound)
                return count--;
            else
                return lowerbound;
        }
    };
}
using namespace CounterNameSpace;
int main() {
    upperbound = 100;
    lowerbound = 0;

    counter ob1(10);

    int i;

    do{
        i=ob1.run();
        cout<<i<<" ";
    }while(i>lowerbound);
    cout <<endl;

    counter ob2(20);
    do{
        i=ob2.run();
        cout<<i<<" ";
    }while(i>lowerbound);
    cout<<endl;

    ob2.reset(100);
    lowerbound = 90;
    do{
        i=ob2.run();
        cout<<i<<" ";
    }while(i>lowerbound);

    return 0;
}


using语句
using namespace name;
using name::member;

匿名的命名空间
namespace { // declarations }

静态类成员
静态类成员,所有的实例都共享一个变量.
访问有两种方式,一种是直接在类成员函数中用 变量名访问,一种是用 :: 访问

静态类成员函数
虚拟静态成员函数是不允许的
const 和 volatile也是不可以用


Runtime Type Identification (RTTI)
#include <iostream>
#include <typeinfo>
using namespace std;

class MyClass{
};


int main() {
    int i,j;
    float f;
    MyClass ob;

    cout<<"The type of i is: "<<typeid(i).name();
    cout<<endl;
    cout<<"The type of f is: "<<typeid(f).name();
    cout<<endl;
    cout<<"The type of ob is: "<<typeid(ob).name();
    cout<<endl;
    cout<<endl;

    if(typeid(i) == typeid(j))
        cout<<"The types of i and j are the same\n";

    if(typeid(i) == typeid(f))
            cout<<"The types of f and j are the same\n";
    cin >> i;
    return 0;
}


四种强制转型形式:

  C++ 同时提供了四种新的强制转型形式(通常称为新风格的或 C++ 风格的强制转型):
  const_cast(expression)
  dynamic_cast(expression)
   reinterpret_cast(expression)
  static_cast(expression)

  每一种适用于特定的目的:

  ·dynamic_cast 主要用于执行“安全的向下转型(safe downcasting)”,也就是说,要确定一个对象是否是一个继承体系中的一个特定类型。
                  它是唯一不能用旧风格语法执行的强制转型,也是唯一可能有重大运行时代价的强制转型。
    
    ·static_cast 可以被用于强制隐型转换(例如,non-const 对象转型为 const 对象,int 转型为 double,等等),
                 它还可以用于很多这样的转换的反向转换(例如,void* 指针转型为有类型指针,基类指针转型为派生类指针),
                 但是它不能将一个 const 对象转型为 non-const 对象(只有 const_cast 能做到),它最接近于C-style的转换。
    
  ·const_cast 一般用于强制消除对象的常量性。它是唯一能做到这一点的 C++ 风格的强制转型。

  ·reinterpret_cast 是特意用于底层的强制转型,导致实现依赖(implementation-dependent)(就是说,不可移植)的结果,
                  例如,将一个指针转型为一个整数。这样的强制转型在底层代码以外应该极为罕见。
  评论这张
 
阅读(160)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017