终于入门一款初级魔法后,我就开始憧憬高级货了。实现了时间刻度抽象模型后,就需要针对Year,Month,Day等具体的时间刻度进行细致的规划。当然,踩雷也是必不可少的必须课了。
首先针对Year,它与时间刻度基类在行为上存在几点不同点:
- Year已经在日常时间里已经是最大时间刻度单位,因此它并不具有parent。
- Year 不需要进位处理,并且不能小于1970。
因此,我通过具体的子类去进行模型上的调整:
class Year : public TimeScale
{
public:
Year(int year);
void operator+(const int i) override;
void operator-(const int i) override;
~Year();
};
datetime::Year::Year(int year) : datetime::TimeScale{year, datetime::IYDT_MAX_YEAR} {}
void datetime::Year::operator+(int i)
{
setValue(value + 1);
recheckChild();
}
void datetime::Year::operator-(int i)
{
int result = value - i;
if (result >= 1970)
{
setValue(result);
recheckChild();
}
}
datetime::Year::~Year() {}
然后是Month,Month和时间刻度基本行为保持一致,但是唯一一点不同的是Month的数值表示方式是1~12而不是0~11。因此需要Month的数值以及进位进行处理。
class Month : public TimeScale
{
protected:
void setValue(int result) override;
public:
Month(TimeScale *year, int month);
void operator+(const int i) override;
void operator-(const int i) override;
~Month();
};
void datetime::Month::setValue(int result)
{
value = result % max + 1;
}
void datetime::Month::operator+(int i)
{
int result = value + i - 1;
setValue(result);
int carry = result / max;
if (carry > 0)
{
handleCarry(carry);
}
else
{
recheckChild();
}
}
void datetime::Month::operator-(int i)
{
int carry = i / max;
int result = value - i % max - 1;
setValue(result >= 0 ? result : result + max);
if (result < 0)
{
carry++;
}
if (carry > 0)
{
handleCarry(0 - carry);
}
else
{
recheckChild();
}
}
datetime::Month::Month(TimeScale *year, int month) : datetime::TimeScale{year, month, datetime::IYDT_MAX_MONTH} {}
datetime::Month::~Month(){};
当然中间也碰到不少语法上的问题。
- 问题:constrained by implicitly private inheritance here
这是一个关于继承的知识点。默认如果没有显式的访问标识符声明,子类继承父类都是私有继承,这个在Java和C#里面是没有这样的约束的。所以我就犯了下面的错误:
class Year : TimeScale
{
public:
Year(int year);
void operator+(const int i) override;
void operator-(const int i) override;
~Year();
};
然后当我初始化Year的实例并使用操作的时候就得到上面的错误。正确的方式是改成public继承。
class Year : public TimeScale
- 问题:deleted function 'handleCarry' cannot override a non-deleted function
这个错误是我在想要消除Year的进位操作的时候得到的。因为Year已经是时间里面的最大时间刻度,理论上它是没有进位的。我起初的方案是将进位函数方法声明为delete就解决这个问题了:
void handleCarry(int carry) = delete;
事实上呢,是我太单纯了。错误信息很好的表明了我犯了什么错误。那就是不同删减一个重载的虚函数。
我也试过下面的方式:
void handleCarry(int carry) = 0;
一样会得到类似的错误信息。所以最终我只能曲线救国,重写了Year的+,-操作符函数。
- 问题:expected function body after function declarator
这个错误字面上很好理解就是我的函数实现发生在了我函数定义前。起先我百思不解不得其解。后面我慢慢领悟到在错误的地方。因为我起先是这么声明Year的:
class Year : TimeScale
{
public:
Year(int year);
~Year();
};
但是呢,我在cpp代码文件里又实现了Year的operator+和operator-函数方法,导致报错。因为我认为我已经在TimeScale里面已经声明了函数,因此我不需要在Year里再声明一次。事实上是你必须要在Year里面再声明一次。
- 问题:override 不能出现在函数体定义的末尾。
这个错误我没有记下具体的错误信息。具体原因是我在Year里声明了operator+并加以override标识。同时我在cpp代码文件的operator+函数实现里也以override标识,然后报错。事实上,cpp代码文件里的override并不需要。其实不光是override,连virtual标识也不需要。