在類

2013-11-26 35 views
1

中調用的覆蓋[]運算符的錯誤版本我有一個簡單的二維線類,它包含兩個雙精度矢量。我已經添加了getValue和setValue函數,但是更喜歡公共接口使方括號運算符與這些函數並用。下面的代碼顯示的實施和使用:在類

#include <vector> 
#include <algorithm> 
#include <cassert> 

class Simple2DLine 
{ 
public: 
    Simple2DLine(); 
    // Simple read method with linear interpolation 
    double getValue(double x) const; 
    // Simple write method, adds a curve point, keeping the arrays sorted 
    void setValue(double x, double y); 

    double& operator [](double x); 
    const double operator [](double x) const; 
private: 
    std::vector<double> m_X; 
    std::vector<double> m_Y; 
    int getNearestIndex(double x) const; 
}; 

Simple2DLine::Simple2DLine() 
{ 

} 

void Simple2DLine::setValue(double x, double y) 
{ 
    // Get the index of the point at or just before 'x' 
    int idx = getNearestIndex(x); 

    // Check if the exact point already exists. 
    if (idx >= 0) 
    { 
     if (m_X[idx] == x) 
     { 
      m_Y[idx] = y; 
      return; 
     } 
     else 
     { 
      // Insert adds the value just BEFORE idx, so increment it before inserting. 
      ++idx; 
      m_X.insert(m_X.begin() + idx,x); 
      m_Y.insert(m_Y.begin() + idx,y); 
      return; 
     } 
    } 

    // Otherwise, just insert at the front. 
    m_X.insert(m_X.begin(),x); 
    m_Y.insert(m_Y.begin(),y); 
} 

double Simple2DLine::getValue(double x) const 
{ 
    // Make sure there are points - if not, return 0. 
    if (m_X.size() == 0) 
    { 
     return 0; 
    } 

    // Make sure it's not out of bounds. 
    if (x < m_X.front() || x > m_X.back()) 
    { 
     return 0; 
    } 

    // Check if it's at or after the last point 
    if (x == m_X.back()) 
    { 
     return m_X.back(); 
    } 

    // Find the point just before the given point. 
    int idx = getNearestIndex(x); 

    // Check if we're on the exact point 
    if (m_X[idx] == x) 
    { 
     return m_X[idx]; 
    } 
    else 
    { 
     // Find the distance from the nearest point and linearly interpolate. 
     double dist = x - m_X[idx]; 

     return m_Y[idx] + dist * (m_Y[idx + 1] - m_Y[idx])/(m_X[idx + 1] - m_X[idx]); 
    } 
} 

double& Simple2DLine::operator [](double x) 
{ 
    // Create a space for the new value 
    setValue(x,0.0); 
    int idx = getNearestIndex(x); 
    return m_Y[idx]; 
} 

const double Simple2DLine::operator [](double x) const 
{ 
    return getValue(x); 
} 

// Returns the index of the point at or just before 'x'. Invalid values return -1. 
int Simple2DLine::getNearestIndex(double x) const 
{ 
    if (m_X.empty()) 
    { 
     return -1; 
    } 

    std::vector<double>::const_iterator xBegin(m_X.begin()); 
    std::vector<double>::const_iterator xEnd(m_X.end()); 

    // Get an iterator to the first value GREATER than our search value 
    std::vector<double>::const_iterator it = upper_bound(xBegin,xEnd,x); 

    // If the iterator is at the beginning, all values are greater 
    if (it == xBegin) 
    { 
     return -1; 
    } 

    // Otherwise, decrement the iterator by 1, and return its' distance from the start. 
    return (it - 1) - xBegin; 
} 

int main(int argc, char** argv) 
{ 
    Simple2DLine tda; 

    tda.setValue(0.0,10.0); 
    tda.setValue(1.0,15.0); 
    tda.setValue(2.0,20.0); 
    tda.setValue(3.0,25.0); 

    double tmp = tda.getValue(0.5); 
    assert(abs(tmp - 12.5) < 0.000001); 
    tmp = tda.getValue(1.5); 
    assert(abs(tmp - 17.5) < 0.000001); 
    tmp = tda.getValue(2.5); 
    assert(abs(tmp - 22.5) < 0.000001); 

    // Here, the wrong version of the overridden operator is being called. 
    tmp = tda[1.5]; 
    tda[2.5] = 22.5; 
} 

當我以下列方式訪問該線對象,操作的正確版本被稱爲(非const)

tda[2.5] = 22.5; 

然而,當我嘗試使用const版本,如下所示:

tmp = tda[1.5]; 

調用非const版本。我的實施中是否有錯誤?或者以這種方式訪問​​課程是不可能的?

回答

7

在const對象上調用const版本。所以如果你有一個聲明爲const Simple2DLine tda的對象,將調用const重載版本operator[]

實際上,你會看到const對象作爲函數的參數,如:

void foo(const Simple2DLine& tda) 
{ 
    std::cout<< tda[0]; 
} 

在那裏,你會發現const的重載被調用的函數。

你的const重載operator[]仍然可以返回一個引用。

+0

好的,理解。我想我可以在我的其他代碼中完成這項工作。謝謝您的幫助! – DaveM

2

你是否認爲const操作符必須被自動調用,因爲包含它的表達式出現在等式的右邊?這不是它的工作方式。如果你有一個const對象,const的版本將被調用。

你可以例如嘗試將對象分配給一個const引用。

Simple2DLine const & tdaconst = tda; 
tmp = tdaconst[1.5]; 

在上面的代碼中,將會調用const版本。