D语言中国主页  D语言编辑器SciTE4D   DWin库 D语言官方网站
D语言编译器1.x最新版 OpenSource   Tango   webnews  Wiki

查看完整版本: 18 D语言 运算符重载 Operator Overloading

yidabu 2007-4-26 15:58

18 D语言 运算符重载 Operator Overloading

18 D语言 运算符重载 Operator Overloading知识若不分享 实在没有意义 http://www.d-programming-language-china.org 20070423点击下面网址查看原文:http://www.d-programming-language-china.org        by:        uFramer        D语言论坛 http://www.d-programming-language-china.org        from:        http://www.digitalmars.com/d/operatoroverloading.html        version:        基于D 1.013        (Apr 19, 2007)        运算符重载就是重新解释作用于特定结构或者类的一元或二元运算符的含义,被重新解释的运算符是作为结构或类的成员实现的。通过重载,我们只需使用原来的语法就可以得到我们想要的结果。Unary Operator Overloading一元运算符重载        Overloadable Unary Operators op        opfunc        -e opNeg        +e opPos        ~e opCom        e++ opPostInc        e-- opPostDec        cast(type)e opCast        假设可被重载的运算符为 op ,对应的类或结构成员函数名为 opfunc ,语法:        [Copy to clipboard] [ - ]CODE:                                op a                被解释为:        [Copy to clipboard] [ - ]CODE:                                a.opfunc()                其中 a 是类或结构的引用。        1 Overloading ++e and --e        因为按照定义 ++e 在语义上等价于 (e += 1) ,表达式 ++e 会被重写为 (e += 1) ,然后按照这种形式应用运算符重载。--e 的情形与之类似。( 本文出处: http://www.d-programming-language-china.org )        2 示例        [Copy to clipboard] [ - ]CODE:                                class A { int opNeg(); }                A a;                -a;    // 等价于 a.opNeg();                                class A { int opNeg(int i); }                A a;                -a;    // 等价于 a.opNeg(), 这是错误                3 Overloading cast(type)e        会调用成员函数 e.opCast() ,并且 opCast() 的返回值被隐式地转换为 type 。因为不能基于返回值重载,所以每个结构或者类只能有一个 opCast 函数。重载转型操作符并不影响隐式转型,只能用于显式转型。        [Copy to clipboard] [ - ]CODE:                                struct A                {                    int opCast() { return 28; }                }                                void test()                {                    A a;                                    long i = cast(long)a;        // i 被设为 28L                    void* p = cast(void*)a;     // 错误,不能隐式地转换 int 为 void*                    int j = a;            // 错误,不能隐式地转换 A 为 int                }        Binary Operator Overloading        1 Overloadable Binary Operators                Overloadable Binary Operators        op        commutative?        opfunc        opfunc_r                + yes opAdd opAdd_r        - no opSub opSub_r        * yes opMul opMul_r        / no opDiv opDiv_r        % no opMod opMod_r        & yes opAnd opAnd_r        | yes opOr opOr_r        ^ yes opXor opXor_r        << no opShl opShl_r        >> no opShr opShr_r        >>> no opUShr opUShr_r        ~ no opCat opCat_r        == yes opEquals -        != yes opEquals -        < yes opCmp -        <= yes opCmp -        > yes opCmp -        >= yes opCmp -        = no opAssign -         += no opAddAssign -        -= no opSubAssign -        *= no opMulAssign -        /= no opDivAssign -        %= no opModAssign -        &= no opAndAssign -        |= no opOrAssign -        ^= no opXorAssign -        <<= no opShlAssign -        >>= no opShrAssign -        >>>= no opUShrAssign -        ~= no opCatAssign -        in no opIn opIn_r                 给定一个二元可重载运算符 op 和它对应的名为 opfunc 和 opfunc_r 的类或结构成员函数,则下面的语法:        [Copy to clipboard] [ - ]CODE:                                a op b                会按顺序应用下面的规则,来决定使用那种形式:        表达式被重写为下面两种形式:        [Copy to clipboard] [ - ]CODE:                                a.opfunc(b)                b.opfunc_r(a)                如果 a.opfunc 或 b.opfunc_r 函数两者之一存在,就应用重载解析从中选出一个最合适的形式。如果函数存在,但是参数却不匹配,则被视为错误。        如果运算符是可交换的,会尝试下面的形式:( 本文出处: http://www.d-programming-language-china.org )        [Copy to clipboard] [ - ]CODE:                                a.opfunc_r(b)                b.opfunc(a)                如果 a 或者 b 是结构或者类对象的引用,就是错误。(译注:即如果类或结构没有重载上述某个运算符,就不能进行相应的运算。)        2 示例        [Copy to clipboard] [ - ]CODE:                                class A { int opAdd(int i); }                A a;                a + 1;    // equivalent to a.opAdd(1)                1 + a;    // equivalent to a.opAdd(1)                class B { int opDiv_r(int i); }                B b;                1 / b;    // equivalent to b.opDiv_r(1)                class A { int opAdd(int i); }                class B { int opAdd_r(A a); }                A a;                B b;                a + 1;    // equivalent to a.opAdd(1)                a + b;    // equivalent to b.opAdd_r(a)                b + a;    // equivalent to b.opAdd_r(a)                class A { int opAdd(B b);    int opAdd_r(B b); }                class B { }                A a;                B b;                a + b;    // equivalent to a.opAdd(b)                b + a;    // equivalent to a.opAdd_r(b)                class A { int opAdd(B b);    int opAdd_r(B b); }                class B { int opAdd_r(A a); }                A a;                B b;                a + b;    // ambiguous: a.opAdd(b) or b.opAdd_r(a)                b + a;    // equivalent to a.opAdd_r(b)                3 Overloading == and !=        这两个运算符都使用 opEquals() 函数。表达式 (a == b) 被重写为 a.opEquals(b) ,而 (a != b) 被重写为 !a.opEquals(b) 。        成员函数 opEquals() 是 Object 的一部分,定义为:        [Copy to clipboard] [ - ]CODE:                                int opEquals(Object o);                这样所有的类对象都有 opEquals() 。        But every class definition which will be using == or != should expect to need to override opEquals. The parameter to the overriding function must be of type Object, not the type for the class.        Structs and unions (hereafter just called structs) can provide a member function:( 本文出处: http://www.d-programming-language-china.org )        [Copy to clipboard] [ - ]CODE:                                int opEquals(S s)                or:        [Copy to clipboard] [ - ]CODE:                                int opEquals(S* s)                where S is the struct name, to define how equality is determined.( 本文出处: http://www.d-programming-language-china.org )        如果结构没有声明 opEquals() 函数,就会按位比较两个结构的内容以测试相等还是不相等。        Note: Comparing a reference to a class object against null should be done as:        [Copy to clipboard] [ - ]CODE:                                if (a is null)                and not as:        [Copy to clipboard] [ - ]CODE:                                if (a == null)                The latter is converted to:        [Copy to clipboard] [ - ]CODE:                                if (a.opEquals(null))                which will fail if opEquals() is a virtual function.        4 Overloading and >=        这些比较运算符都使用 opCmp() 函数。表达式 (a op b) 被重写为 (a.opCmp(b) op 0) 。可交换的运算被重写为 (0 op b.opCmp(a)) 。        成员函数 opCmp() 是 Object 的一部分,定义为:        [Copy to clipboard] [ - ]CODE:                                int opCmp(Object o);                这样所有的类对象都有 opCmp() 。        如果结构没有声明 opCmp() 函数,试图比较两个结构的大小就是一个错误。        原理        同时拥有 opEquals() 和 opCmp() 两个函数的原因为:        有时,测试相等性会比测试小于或大于要高效。        Having an opCmp defined in Object makes it possible to make associative arrays work generically for classes.( 本文出处: http://www.d-programming-language-china.org )        对于某些对象来说,测试小于或者等于根本就没有意义。This is why Object.opCmp throws a runtime error. opCmp must be overridden in each class for which comparison makes sense.        The parameter to opEquals and opCmp for class definitions must be of type Object, rather than the type of the particular class, in order to override the Object.opEquals and Object.opCmp functions properly.Function Call Operator Overloading f()        函数调用运算符,(),可以通过声明名为 opCall 的函数来重载:        [Copy to clipboard] [ - ]CODE:                                struct F                {                    int opCall();                    int opCall(int x, int y, int z);                }                                void test()                {    F f;                    int i;                                    i = f();        // 等价于 i = f.opCall();                    i = f(3,4,5);        // 等价于 i = a.opCall(3,4,5);                }                采用这种方法,结构或对象可以表现得像函数一样。Array Operator Overloading        1 Overloading Indexing a[i]        重载索引运算符 a[i]        数组索引运算符,[],可以通过声明名为 opIndex 的函数来重载,该函数可以有一个或多个参数。至于对数组赋值,可以通过声明名为 opIndexAssign 的函数来重载,该函数可以有两个或多个参数。第一个参数是赋值表达式的右值。        [Copy to clipboard] [ - ]CODE:                                struct A                {                    int opIndex(size_t i1, size_t i2, size_t i3);                    int opIndexAssign(int value, size_t i1, size_t i2);                }                                void test()                {    A a;                    int i;                                    i = a[5,6,7];    // same as i = a.opIndex(5,6,7);                    a[i,3] = 7;        // same as a.opIndexAssign(7,i,3);                }                采用这种方法,结构或类对象可以表现得像数组一样。(译注:opApply??怎么没提??)        注意:目前,数组索引重载不能用于 op=、++ 或 -- 运算符的左值。( 本文出处: http://www.d-programming-language-china.org )        2 Overloading Slicing a[] and a[i .. j]        重载切片运算符 a[] 和 a[i .. j]        重载切片运算符意味着重载例如 a[] 和 a[i .. j] 这样的表达式。This can be done by declaring a function named opSlice. Assignment to a slice can be done by declaring opSliceAssign.        [Copy to clipboard] [ - ]CODE:                                class A                {                    int opSlice();                     // overloads a[]                    int opSlice(size_t x, size_t y);            // overloads a[i .. j]                                    int opSliceAssign(int v);                // overloads a[] = v                    int opSliceAssign(int v, size_t x, size_t y); // overloads a[i .. j] = v                }                                void test()                {    A a = new A();                    int i;                    int v;                                    i = a[];        // same as i = a.opSlice();                    i = a[3..4];    // same as i = a.opSlice(3,4);                                    a[] = v;        // same as a.opSliceAssign(v);                    a[3..4] = v;    // same as a.opSliceAssign(v,3,4);                }        Assignment Operator Overloading        The assignment operator = can be overloaded if the lvalue is a struct or class aggregate, and opAssign is a member function of that aggregate.        The assignment operator cannot be overloaded for rvalues that can be implicitly cast to the lvalue type. Furthermore, the following parameter signatures for opAssign are not allowed:        [Copy to clipboard] [ - ]CODE:                                opAssign(...)                opAssign(T)                opAssign(T, ...)                opAssign(T ...)                opAssign(T, U = defaultValue, etc.)                where T is the same type as the aggregate type A, is implicitly convertible to A, or if A is a struct and T is a pointer to a type that is implicitly convertible to A.Future Directions        未来的方向        ‘!, ., &&, ||, ?:, ’和其他少数几个运算符很可能永远都不会变得可重载。( 本文出处: http://www.d-programming-language-china.org )( lastupdate:20070426 最新文章请访问http://www.d-programming-language-china.org )关于一大步成功社区:yidabu提倡在交流中学习,在分享中提高收集感兴趣的知识,写下心得,通过网络与别人一起分享理解一点就实践一步,收获什么就分享什么,成功就是这样一点点一步步累积起来的网络只是一个工具,只有自己身心提高才是实实在在的。d-programming-language-china.org为大家提供一个学习交流各种知识的平台
页: [1]
查看完整版本: 18 D语言 运算符重载 Operator Overloading