我的工作是完全重写一个用于GIS矢量数据处理的旧库。main类封装了一组建筑轮廓,并提供了检查数据一致性的不同方法。这些检查功能有一个可选参数,允许执行某些过程。
例如:
std::vector<Point> checkIntersections(int process_mode = 0);
此方法测试某些建筑轮廓是否相交,并返回相交点。但是,如果您传递一个非null参数,该方法将修改轮廓以删除交叉点。
我认为这很糟糕(在调用站点,不熟悉代码库的读者会认为一个名为checkSomething的方法只执行检查,不修改数据),我想改变这一点。我还想避免代码重复,因为检查和处理方法大多相似。
所以我在想这样的事情:
// a private worker
std::vector<Point> workerIntersections(int process_mode = 0)
{
// it's the equivalent of the current checkIntersections, it may perform
// a process depending on process_mode
}
// public interfaces for check and process
std::vector<Point> checkIntersections() /* const */
{
workerIntersections(0);
}
std::vector<Point> processIntersections(int process_mode /*I have different process modes*/)
{
workerIntersections(process_mode);
}
但这迫使我打破常量的正确性,因为workerIntersections是一种非常量方法。
如何将检查和处理分开,避免代码重复并保持常量正确性?
正如您所指出的,您的建议将破坏const-correctness
。这是因为您的建议本质上包括用新的interface
包装现有代码,而不是内部的redesign
。这种方法有严重的局限性,因为它直接受到底层块的影响。
相反,我建议您重新设计现有的代码,并将checkIntersections
分解为您需要的两个公共方法。checkIntersections
将包括检查部分,processIntersections
将包括对checkIntersections
的调用和基于checkIntersections
的结果的处理代码。
在这种特殊情况下,破坏常量正确性应该无关紧要。您(正如workerIntersections()
的作者所知,如果从processIntersections()
(一个非常量函数)调用它,它只会执行非常量操作。因此,像这样实现checkIntersections()
是安全的:
std::vector<Point> checkIntersections() const
{
const_cast<TypeOfThis*>(this)->workerIntersections(0);
}
当然,您必须确保workerIntersections()
在使用0
调用时确实只执行const操作。
const_cast
存在于该语言中是有原因的,主要是与忽略常量正确性的遗留代码的互操作性。这正是你正在做的,所以只要你安全地做,你就可以使用const_cast
。