qiezi的学习园地

AS/C/C++/D/Java/JS/Python/Ruby

  C++博客 :: 首页 :: 新随笔 ::  ::  :: 管理 ::
新特性:
1、给委托增加ptr属性,指向委托所绑定的对象。
这是一个语法糖,dg.ptr被转化为cast(void*)dg,它只能作右值,所以除了能读取它以外,在语法上禁止对它赋值。要想把委托绑定到不同的对象,你只能自己实现:

class Foo{
    
int foo;
public:
    
this(int foo){
        
this.foo = foo;
    }

    
void bar(){
        writefln(foo);
    }
}

void main(){

    alias 
void delegate() DG;
    DG dg 
= &(new Foo(1)).bar;

    Foo[
10] foos;
    
foreach(int i, inout Foo foo; foos){
        foo 
= new Foo(i);
    }

    
void** ptr = cast(void**)&dg;
    
foreach(Foo foo; foos){
        
*ptr = cast(void*)foo;
        dg();
    }
}

这种方式也不是我们所希望的,一般来说委托绑定到多个对象时,因为是取到某成员函数指针,再进行绑定。比如模拟一个ActiveSupport所扩展的一个ruby.Array#map用法:

import std.stdio;

class Foo{
    
int foo;
public:
    
this(int foo){
        
this.foo = foo;
    }

    
void bar(){
        writefln(foo);
    }
}

class Array(T){
    
private:
    T[] data;

    
public:
    
this(T[] data){
        
this.data = data[0 .. length];
    }

    
void map(void function() func){
        
void delegate() dg;
        
void** funcPtr = cast(void**)&dg + 1;
        
*funcPtr = func;
        
void ** ptr = cast(void**)&dg;
        
foreach(T v; data){
            
*ptr = cast(void*)v;
            dg();
        }
    }
}

void main(){
    auto arr 
= new Array!(Foo)([new Foo(1), new Foo(2), new Foo(3)]);
    arr.map(
&Foo.bar);
}

是的,delegate内部保存了2个指针,所以我们可以容易地hack它。

[注:上面的main函数中数组直接量赋给栈对象也是这个版本中新增的内容,显然只能用于static对象是很鸡肋的。这里简单带过不提。]

[注:上面这个map的模拟并不是ActiveSupport的map扩展的全部用途,那个map还是收集返回值,这里只演示调用语法。ActiveSupport中扩展的map调用语法是map(&:to_s),就可以收集到数组中所有元素调用to_s后的返回值。]

2、给内嵌内的实例增加outer属性,指向外层对象。

import std.stdio;

class Outer{
    
class Inner{}

    
this(){
        Inner inner 
= new Inner;
        inner.outer.foo();
    }

    
void foo(){
        writefln(
"foo");
    }
}

void main(){
    Outer outer 
= new Outer;
}

这个特性可能应用并不是很广吧。

3、mixin多个析构函数。

template A(){
    
this(){
    }
    
~this(){
        writefln(
"A::~A()");
    }
}

template B(){
    
~this(){
        writefln(
"B::~B()");
    }
}

class C{
    mixin A;
    mixin B;
}

void main(){
    C c 
= new C;
    delete c;
}

这些析构函数会和mixin相反的顺序执行。我不明白的是,为什么不让mixin多个构造函数?为何不让这些构造函数晚于被mixin的类(上面的C类)的构造函数,并按mixin进来的顺序执行?
posted on 2006-10-05 09:23 qiezi 阅读(634) 评论(5)  编辑 收藏 引用 所属分类: D