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 == ba无效时会崩溃,==为opEquals.
转换回GTIN之后,可再次转换,并调用转换函数.
在实现它们的类中,opEqualsopCmp都需要遵循相同模式.
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_castcast()/cast(const)
dynamic_castcast(some_object)
reinterpret_cast*cast(T*)cast(void*)&x
static_castopCast/构造器
posted @   zjh6  阅读(11)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示