前の日 / 次の日 / 最新 / 2009-09

01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

2009-09-01 Tue

classinfo.vtbl の状態がおかしい。 [D言語]

同名のmutable/const/immutableメンバ関数のオーバーロード

オーバーライドした関数を const/immutable でオーバーロードすると、
classinfo.vtbl で読める vtable の状態がおかしい。

以下実験してみた。

D のすべてのクラスは、 Object を継承している。

class Base
{
}

void main()
{
    foreach(i,p;Base.classinfo.vtbl)
    {
        writefln("Base vtbl[%d] = %x",i,p);
    }
}
Base vtbl[0] = xxxxxx //ClassInfo
Base vtbl[1] = xxxxxx //Object.toString
Base vtbl[2] = xxxxxx //Object.toHash
Base vtbl[3] = xxxxxx //Object.opCmp
Base vtbl[4] = xxxxxx //Object.opEquals

Base に一つの関数を定義してみる。

class Base
{
    void funcA(){}
}

void main()
{
    foreach(i,p;Base.classinfo.vtbl)
    {
        writefln("Base vtbl[%d] = %x",i,p);
    }
}
Base vtbl[0] = xxxxxx //ClassInfo
Base vtbl[1] = xxxxxx //Object.toString
Base vtbl[2] = xxxxxx //Object.toHash
Base vtbl[3] = xxxxxx //Object.opCmp
Base vtbl[4] = xxxxxx //Object.opEquals
Base vtbl[5] = xxxxxx //Base.funcA

Base に3つの関数を定義してみる。

class Base
{
    void funcA(){}
    void funcB(){}
    void funcC(){}
}

void main()
{
    foreach(i,p;Base.classinfo.vtbl)
    {
        writefln("Base vtbl[%d] = %x",i,p);
    }
}
Base vtbl[0] = xxxxxx //ClassInfo
Base vtbl[1] = xxxxxx //Object.toString
Base vtbl[2] = xxxxxx //Object.toHash
Base vtbl[3] = xxxxxx //Object.opCmp
Base vtbl[4] = xxxxxx //Object.opEquals
Base vtbl[5] = xxxxxx //Base.funcA
Base vtbl[6] = xxxxxx //Base.funcB
Base vtbl[7] = xxxxxx //Base.funcC

Base の3つの関数をオーバーロードしてみる。

class Base
{
    void funcA(){}
    void funcA(int){}
    void funcA(long){}
}

void main()
{
    foreach(i,p;Base.classinfo.vtbl)
    {
        writefln("Base vtbl[%d] = %x",i,p);
    }
}
Base vtbl[0] = xxxxxx //ClassInfo
Base vtbl[1] = xxxxxx //Object.toString
Base vtbl[2] = xxxxxx //Object.toHash
Base vtbl[3] = xxxxxx //Object.opCmp
Base vtbl[4] = xxxxxx //Object.opEquals
Base vtbl[5] = xxxxxx //Base.funcA()
Base vtbl[6] = xxxxxx //Base.funcA(int)
Base vtbl[7] = xxxxxx //Base.funcA(long)

D では、 const や immutable でオーバーロードができる。

class Base
{
    void funcA(){}
    void funcA() const {}
    void funcA() immutable {}
}

void main()
{
    foreach(i,p;Base.classinfo.vtbl)
    {
        writefln("Base vtbl[%d] = %x",i,p);
    }
}
Base vtbl[0] = xxxxxx //ClassInfo
Base vtbl[1] = xxxxxx //Object.toString
Base vtbl[2] = xxxxxx //Object.toHash
Base vtbl[3] = xxxxxx //Object.opCmp
Base vtbl[4] = xxxxxx //Object.opEquals
Base vtbl[5] = xxxxxx //Base.funcA()
Base vtbl[6] = xxxxxx //Base.funcA() const
Base vtbl[7] = xxxxxx //Base.funcA() immutable

継承をしてみる。

class Base
{
    void func(){}
}

class Derived:Base
{
}


void main()
{
    foreach(i,p;Derived.classinfo.vtbl)
    {
        writefln("Derived vtbl[%d] = %x",i,p);
    }
}
Derived vtbl[0] = xxxxxx //ClassInfo
Derived vtbl[1] = xxxxxx //Object.toString
Derived vtbl[2] = xxxxxx //Object.toHash
Derived vtbl[3] = xxxxxx //Object.opCmp
Derived vtbl[4] = xxxxxx //Object.opEquals
Derived vtbl[5] = xxxxxx //Base.func()

オーバーライドをしてみる。
Base.func() を Derived.func() でオーバーライド

class Base
{
    void func(){}
}

class Derived:Base
{
    void func(){}
}


void main()
{
    foreach(i,p;Derived.classinfo.vtbl)
    {
        writefln("Derived vtbl[%d] = %x",i,p);
    }
}
Derived vtbl[0] = xxxxxx //ClassInfo
Derived vtbl[1] = xxxxxx //Object.toString
Derived vtbl[2] = xxxxxx //Object.toHash
Derived vtbl[3] = xxxxxx //Object.opCmp
Derived vtbl[4] = xxxxxx //Object.opEquals
Derived vtbl[5] = xxxxxx //Derived.func()

さらにオーバーロードもしてみる
        Base.func(int) を Derived.func(int) のオーバーライド
Base.func() と Derived.func(int) のオーバーロード

class Base
{
    void func(){}
    void func(int){}
}

class Derived:Base
{
    alias Base.func func;
    override void func(int){}
}


void main()
{
    foreach(i,p;Derived.classinfo.vtbl)
    {
        writefln("Derived vtbl[%d] = %x",i,p);
    }
}
Derived vtbl[0] = xxxxxx //ClassInfo
Derived vtbl[1] = xxxxxx //Object.toString
Derived vtbl[2] = xxxxxx //Object.toHash
Derived vtbl[3] = xxxxxx //Object.opCmp
Derived vtbl[4] = xxxxxx //Object.opEquals
Derived vtbl[5] = xxxxxx //Base.func()
Derived vtbl[6] = xxxxxx //Derived.func(int)

Base.func(int) を Derived.func(int) のオーバーライド
Base.func() と Derived.func(int) と Derived.func(long) のオーバーロード

class Base
{
    void func(){}
    void func(int){}
}

class Derived:Base
{
    alias Base.func func;
    override void func(int){}
    void func(long){}
}


void main()
{
    foreach(i,p;Derived.classinfo.vtbl)
    {
        writefln("Derived vtbl[%d] = %x",i,p);
    }
}
Derived vtbl[0] = xxxxxx //ClassInfo
Derived vtbl[1] = xxxxxx //Object.toString
Derived vtbl[2] = xxxxxx //Object.toHash
Derived vtbl[3] = xxxxxx //Object.opCmp
Derived vtbl[4] = xxxxxx //Object.opEquals
Derived vtbl[5] = xxxxxx //Base.func()
Derived vtbl[6] = xxxxxx //Derived.func(int)
Derived vtbl[7] = xxxxxx //Derived.func(long)

Base.func(int) をオーバーライドした、
Derived.func(int) を const と immutable でオーバーロード

class Base
{
    void func(){}
    void func(int){}
}

class Derived:Base
{
    alias Base.func func;
    void func(int){}
    void func(int) const{}
    void func(int) immutable{}
    void func(long){}
}


void main()
{
    foreach(i,p;Derived.classinfo.vtbl)
    {
        writefln("Derived vtbl[%d] = %x",i,p);
    }
}
// const/immutable でオーバーロードした関数はどこ?
Derived vtbl[0] = xxxxxx //ClassInfo
Derived vtbl[1] = xxxxxx //Object.toString
Derived vtbl[2] = xxxxxx //Object.toHash
Derived vtbl[3] = xxxxxx //Object.opCmp
Derived vtbl[4] = xxxxxx //Object.opEquals
Derived vtbl[5] = xxxxxx //Base.func()
Derived vtbl[6] = xxxxxx //Derived.func(int)
Derived vtbl[7] = xxxxxx //Derived.func(long)

ここから先は、dmd のソースを調べるのか。

src/dmd/class.c
src/dmd/func.c
ここら辺かな?