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

时间:2015-03-18 15:37:41

标签: c++ thread-safety method-overriding

我有一个基类Point(表示空间中的2D点),它对于移动操作是非线程安全的;所以我定义了一个继承的类LockedPoint,它覆盖了基类中的两个方法: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> )

通过&#34;解锁&#34;直观地看到问题。 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已被&#34;损坏&#34;,正如预期的那样(它应该等于(0,0)到最后,并且它不会)。如果我将p更改为LockedPoint,则仍会调用moveBy的基本版本(通过打印调试进行验证)。

我读了方法&#34;覆盖&#34; (显然更正确地称为&#34;方法隐藏&#34;),根据我的理解,如果重写方法与基本方法具有相同的签名,它会隐藏基本版本,而是被调用。为什么然后调用基本方法,尽管2具有相同的签名?我唯一能想到的是因为我在Point的参数列表中指定了messWithPoint,它按照字面意思并调用Point& #39; s版本。如果我将签名更改为void messWithPoint(LockedPoint& p, int type),则生成的LockedPoint(0,0),符合预期。不应该&#34;看&#34;传递的LockedPoint会覆盖使用过的方法,并使用&#34;最少隐藏的&#34;版本

如果它不是如何工作的,有没有办法指定基类,但让它使用任何可用的重写版本?

1 个答案:

答案 0 :(得分:2)

成员函数不是虚函数,因此使用编译时已知类中的函数。

然而,对于一个简单的类,例如点,使用虚拟成员函数或提供自动互斥违背了C ++的想法,即不支付你不使用的内容。

只需复制点。