C++ - 方法覆盖未按预期表达

C++ - Method Override Isn't Expressed as Expected

我有一个 Base class Point(表示 space 中的一个 2D 点),它对于移动操作是非线程安全的;所以我定义了一个继承的 class LockedPoint 来覆盖基础 class 中的 2 个方法:moveTomoveBy:

void Point::moveTo(float xPos, float yPos) {
    x = xPos;
    y = yPos;
}

void Point::moveBy(float xOff, float yOff) {
    x += xOff;
    y += yOff;
}

void LockedPoint::moveTo(float xPos, float yPos) {
    MutGuard m(lock);
    x = xPos;
    y = yPos;
}

void LockedPoint::moveBy(float xOff, float yOff) {
    MutGuard m(lock);
    x += xOff;
    y += yOff;
}

( where x and y = private member variables,
    lock = a private mutex, and
    MutGuard = typedef lock_guard<mutex> )

为了直观地看到 "unlocked" Point 的问题,我写了一个测试例程:

void sleepForMS(long ms) {
    std::this_thread::sleep_for(std::chrono::milliseconds(ms));
}

void messWithPoint(Point& p, int type) {

    float n = 1;
    if (type) n *= -1;

    for (long i = 0; i < 10000; i++) {

        p.moveBy(n, n);

        sleepForMS(rand() % (type ? 2 : 3));

        if (i % 500 == 0)
            std::cout << i << ":\t" << p << std::endl;

    }

}


int main(int argc, char* argv[]) {
    using namespace std;

    Point p;

    thread t1(messWithPoint, std::ref(p), 0);

    sleepForMS(33);

    thread t2(messWithPoint, std::ref(p), 1);

    cout << "Started\n";

    t1.join();
    t2.join();

    cout << p << endl;
}

使用 Point,结果 p 是 "corrupted",正如预期的那样(到最后它应该等于 (0,0),但事实并非如此)。但是,如果我将 p 更改为 LockedPoint,仍会调用 moveBy 的基本版本(通过打印调试验证)。

我阅读了方法 "overriding"(显然更正确地称为 "method hiding"),据我所知,如果重写方法与基方法具有相同的签名,它会隐藏基版本,并改为调用。尽管 2 具有相同的签名,但为什么要调用基本方法?我唯一能想到的是因为我在 messWithPoint 的参数列表中指定了 Point,它按字面意思调用 Point 的版本。如果我将签名更改为 void messWithPoint(LockedPoint& p, int type),结果 LockedPoint 就是预期的 (0,0)。是不是应该"see"传递的LockedPoint覆盖used方法,使用"least hidden"版本?

如果这不是它的工作方式,是否有一种方法可以指定采用基础 class,但让它使用任何可用的覆盖版本?

成员函数不是虚函数,所以使用编译时已知的class中的函数。

然而,对于像点这样的简单class,使用虚拟成员函数或提供自动互斥有悖于C++不为不用而付费的理念。

复制积分即可。