2009-09-01
同名の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
ここら辺かな?