zoukankan      html  css  js  c++  java
  • Slice到C++映射

    按:本文是DPWI第6章的笔记。

     

    客户端Slice到C++映射定义的是:怎样把Slice数据类型翻译成C++类型,客户怎样调用操作、传递参数、处理错误。C++映射线程安全,不存在内存管理问题。不建议查看slice2cpp生成的C++映射文件,但建议掌握C++映射规则。

    1、模块映射 
    module M{...}
    映射为
    namespace M{...}

    2、类型映射 
    ⑴基本类型
    Slice     C++ 
    bool   → bool
    byte   → Ice::Byte
    short  → Ice::Short
    int    → Ice::Int
    long   → Ice::Long
    float  → Ice::Float
    double → Ice::Double
    string → std::string
     

    ⑵复杂类型 
    Slice     C++ 
    枚举 →   枚举
    结构 →   结构,支持比较符,可用于Slice词典键类型,支持深度复制、赋值。
    序列 →   std::vector,可以映射为list,dequeue,数组,范围。
    词典 →   std::map。
     

    3、异常映射 
    异常可映射为同名C++类,支持如下操作:
    • ice_name  异常的名字。
    • ice_clone 多态克隆异常,在不知道异常类型情况下复制异常。
    • ice_throw 在不知道某个异常的确切运行时类型的情况下抛出它。
    • ice_print  打印异常的名字,或直接使用重载的<<操作符:
     

    try {
        // ...
    } catch (const Ice::Exception & e) {
        cerr << e << endl;
    }

    出于效率上的考虑,总是通过const引用捕捉异常。这样,编译器就能够生成不调用异常复制构造器的代码(当然,同时也防止异常被切成基类型)。调用操作抛出异常时,该操作的out参数是否赋值无法确定,但是操作的返回值肯定没有返回。

    一条异常路径:

    • Ice::ConnectTimeoutException

    • Ice::TimeoutException

    • Ice::LocalException

    • Ice::UserException

    • Ice::Exception
    很少需要以最深派生类型捕获运行时异常,而是以LocalException捕获它们;对细粒度异常处理感兴趣的,主要是Ice运行时实现。

    4、接口映射 
    module M {
        interface Simple {
            void op();
        };
    };
    客户端,接口映射到类:
              ↓
    namespace IceProxy {
        namespace M {
            class Simple;
        }
    }
    namespace M{
        class Simple; — 代理类
        typedef IceInternal::ProxyHandle< ::IceProxy::M::Simple> SimplePrx; — 代理句柄
        typedef IceInternal::Handle< ::M::Simple> SimplePtr;
    }
    namespace IceProxy {
        namespace M {
            class Simple : public virtual IceProxy::Ice::Object {
            public:
                typedef ::M::SimplePrx ProxyType;
                typedef ::M::SimplePtr PointerType;
                void op();
                void op(const Ice::Context&);
                //....
            };
        };
    }
    IceProxy::M::Simple是服务器Simple接口的客户端代理类,它继承自IceProxy::Ice::Object。接口中的每个操作,代理类都有两个重载的、同名的成员函数。其中一个函数的最后一个参数的类型是Ice::Context——Ice上下文,dictionary<string, string>结构,客户端向服务器发送请求时,将该结构一起发送。

    客户端不能直接实例化代理类:
    IceProxy::M::Simple s;  ← 错误
    客户端只能使用代理句柄SimplePrx访问代理类Simple。代理句柄能够自动管理内存,支持赋值和比较操作符:
    SimplePrx prx1 = ...;
    SimplePrx prx2(prx1);
    prx1=prx2;
    assert(prx1==prx2);
    cout << prx1 << ';' << prx2 << endl; ← 等效方法 prx->ice_toString()
    类似方法:communicator->proxyToString(prx);

    BasePrx base = ...; 
    DerivedPrx derived = DerivedPrx::checkedCast(base); ← 检查转换:远程访问,失败时返回null。
    derived = DerivedPrx::uncheckedCast(base); ← 不检查的转换:不进行远程访问,失败时行为不确定。

    代理方法:
    Ice::ObjectPrx base = communicator->stringToProxy(...);
    HelloPrx hello = HelloPrx::checkedCast(base);
    hello = hello->ice_timeout(10000); 
    hello->sayHello();

    代理比较:
    代理同一性比较:==,!=,<,<=,>,>=比较,布尔比较;
    代理的对象同一性比较:
    bool proxyIdentityLess(p1,p2);
    bool proxyIdentityEqual(p1,p2);
    bool proxyIdentityAndFacetLess(p1,p2);
    bool proxyIdentityAndFacetEqual(p1,p2);

    5、操作映射 
    对于所有被映射的Slice 类型而言都一样:你可以安全地忽略操作的返回值,不管它的类型是什么——返回值总是通过传值返回。如果你忽略返回值,不会发生内存泄漏,因为返回值的析构器会按照需要释放内存。

    in 参数,使用传值或const引用传递;
    out参数,使用引用传递。

    支持链式调用:
    p2->setName(p1->getName()); ← p1,p2为代理

    6、异常处理 
    SimplePrx p = ...; 
    try {
        p->op();
    } catch (const SimpleError & t) {
        cout << "Simple Error: " << t.reason << endl;
    }
    应该总是使用const引用捕捉异常。这样,编译器就能生成不调用异常复制构造器的代码,同时防止异常切成基类型。操作抛出异常后,操作的参数是否已改变不能确定;但是接收操作返回值的变量没有被改写。

    7、类映射: 
    Slice类映射到同名C++类。
    • 每个成员映射为C++类public成员;
    • 每个操作映射为虚成员函数;
    • 类继承自Ice::Object(代理类继承自Ice::ObjectPrx);
    • 两个构造器,一个缺省,一个带有所有成员参数;
    • 生成<class-name>Ptr智能指针(<class-name>Prx是代理句柄)。

    类继承自Ice::Object基类的成员函数:
    • ice_isA:是否支持指定类型ID
    • ice_ping:类可达测试
    • ice_ids:对象支持的类序列,从根类到最深派生类
    • ice_id:类的实际ID
    • ice_staticId:类的静态类型ID
    • ice_hash:类的哈希值
    • ice_clone:多态浅复制
    • ice_preMarshal:整编本类前调用
    • ice_postUnmarshal:解编本类后调用
    • ice_dispatch:请求分派给服务者
    • 比较操作符:== != < <= > >=

    类成员可见性:
    修改类成员的可见性,使用元数据指令:["protected"]

    类的构造函数:
    类的缺省构造函数,构造每个数据成员,简单内置类型不初始化,复杂类型使用该类型自己的缺省构造初始化。
    类的非缺省构造函数,每个数据成员一个参数,可以用一条语句构造和初始化。所有参数按照基类到派生类的顺序,加入参数序列。

    类的操作:
    类的操作被映射为纯虚成员函数,必须创建派生类,实现这些操作,才能使用类。

    类工厂:
    有操作的类必须提供类工厂,无操作的类不必提供类工厂。
    ⑴实现类工厂
    class SimpleFactory : public Ice::ObjectFactory {
    public:
        virtual Ice::ObjectPtr create(const std::string &) {
            assert(type == M::Simple::ice_staticId());
            return new SimpleI;
        }
        virtual void destroy() {}
    };
    ⑵注册类工厂:
    Ice::CommunicatorPtr ic = ...;
    ic->addObjectFactory(new SimpleFactory, M::Simple::ice_staticId());
    ⑶使用类工厂:
    现在,每当Ice实例化M::Simple类时,就会自动调用SimpleFactory的create方法,创建SimpleI类,客户端可以使用该类的op方法。

    类的智能指针:
    Slice 编译器会为每种类类型生成智能指针。对于Slice类<class-name>,编译器会生成叫作<class-name>Ptr 的C++ 智能指针:
        TimeOfDayPtr tod = new TimeOfDayI;
    不能在栈上分配类实例,也不能用静态变量定义类实例。类必须由new分配。

    智能指针是异常安全的,当抛出异常时,智能指针能够安全地析构。但要注意:在构造器中抛出异常,可能使得智能指针不安全;循环引用的情况下,智能指针也会不安全,这种情况下,可以使用Ice::collectGarbage();  收集因循环引用没有释放的对象。当然只有在循环引用的情况下,垃圾收集器才有用。在没有循环引用的情况下,使用垃圾收集器没有意义。把Ice.GC.Interval 设成5,收集器线程就会每5秒运行一次垃圾收集器。

    智能指针的比较只会比较内存地址,即比较两个指针是否指向同一物理类实例。

     

    转自:http://blog.csdn.net/colorado

  • 相关阅读:
    ECMAScript 引用类型Object 对象
    jQuery Form Plugin
    在 PHP5 中使用 DOM 控制 XML
    JavaScript encodeURI()和encodeURIComponent() 函数
    程序员进阶的建议:多看、多写、多交流
    jQuery 取 css zindex 值在各种浏览器中的返回值
    XPath 语法教程(Tutorial_2)
    使用 strpos 需要注意 === 运算符
    关于代码开发规范和原则
    PHP 编写大型网站问题集
  • 原文地址:https://www.cnblogs.com/catkins/p/5270390.html
Copyright © 2011-2022 走看看