dopEquals()和opCast()给我分段错误
public abstract
class GlobalTradeItemNumber
{
// 可仅return _digits.length
public abstract @property
size_t length();
代码:
public
/*
//该行是错的.
//GTIN14 opCast(GTIN14)()//.1
应为
*/
GTIN14 opCast(T : GTIN14)()
{
string currentGTINString = this.toString()[0 .. $-1];
while (currentGTINString.length < 13)
currentGTINString = ('0' ~ currentGTINString);
return new GTIN14(currentGTINString);
}
// 用元编程需要转为其他大小
GTIN13 opCast(T : GTIN13)()
{
string currentGTINString = this.toString()[0 .. $-1];
while (currentGTINString.length < 12)
currentGTINString = ('0' ~ currentGTINString);
return new GTIN13(currentGTINString);
}
参考
.1定义了名为GTIN14的本地模板参数.并隐藏了外部名.
如果用的是模板类,则特化还可提取长度,并且应有可完成这些的函数.或,如果长度为每个子类中的编译时常量(枚举),也可从那里提取它.
用T : class_name加上函数就可修复.
public ulong toNumber()
{
ulong result;
// int exponent = 1;
// exponent *= 10;然后不断乘
for (size_t i = this.length-1; i > 0; i--)
{
result += (this._digits[i] * (10^^(this._digits.length-i)));
}
return result;
}
再看:
public override @trusted
bool opEquals(Object other)
{
/*//两种转换!
GTIN14 b = cast(GTIN14) other;
// 通用动态转换
GTIN14 a = cast(GTIN14) this;
// 调用opCast
*/
GTIN obj = cast(GTIN) other;
if(obj is null) //
//Object可能不是你类实例,可能返回`无效`.
return false; // 不是匹配
GTIN14 b = cast(GTIN14) obj;
GTIN14 a = cast(GTIN14) this;
for (int i; i < a.digits.length; i++)
{
if (a.digits[i] != b.digits[i]) return false;
}
return true;
}
public override @trusted
int opCmp(Object other)
{
// GTIN14 that = cast(GTIN14) other;
// 通用动态转换
GTIN obj = cast(GTIN) other;
if(obj is null) // 同上
return -1; // 不匹配
GTIN14 that = cast(GTIN14) obj;
// 这是自定义转换.
const ulong thisNumber = this.toNumber();
const ulong thatNumber = that.toNumber();
if (thisNumber == thatNumber) return 0;
return ((thisNumber / 10u) > (thatNumber / 10u) ? 1 : -1);
}
麻烦在:相同的cast语法做了两件不同事情
other静态类型是Object通用基类,所以它还不知道你的自定义转换函数.(opCast,作为模板,不能是虚的,因此这不是其他修改模板函数的覆盖行为)
用的是类似C++的动转,c++的转换
试从基类/接口转换回子类,成功得到引用,失败,则返回无效,并段错误.
cast(xxx) this知道是GTIN或其子类.因而,可用自定义opCast来转换.因而a成功,但b失败.
GTIN14 a = new GTIN14("xxx");
Object b = new Object();
assert(a == b);
修复为:Object other转为GTIN基类,再检查null.
用a is null来比较无效.因为a == b在a为无效时会崩溃,==为opEquals.
转换回GTIN之后,可再次转换,并调用转换函数.
在实现它们的类中,opEquals和opCmp都需要遵循相同模式.
在opEquals中,为无效时,我返回假.而opCmp中返回-1.
实现通用模板类:
alias GTIN14 = GlobalTradeItemNumberImpl!14;
alias GTIN13 = GlobalTradeItemNumberImpl!13;
public
class GlobalTradeItemNumberImpl(int size) : GlobalTradeItemNumber
{
public override @property
size_t length()
{
return size;
}
this(string digits)
{
super(digits);
}
}
都在基类中实现功能,可用opCast覆盖.
T opCast(T : GlobalTradeItemNumberImpl!N, int N)()
{
string currentGTINString = this.toString()[0 .. $-1];
while (currentGTINString.length < (N-1))
currentGTINString = ('0' ~ currentGTINString);
return new T(currentGTINString);
}
用alias this改类为构来组合功能.
C++ | D |
|---|---|
const_cast | cast()/cast(const) |
dynamic_cast | cast(some_object) |
reinterpret_cast | *cast(T*)cast(void*)&x |
static_cast | opCast/构造器 |
浙公网安备 33010602011771号