当我使用<set> iterator?</set>时,为什么我不能使用member函数来获取成员变量

时间:2014-10-03 04:38:45

标签: c++ oop stl

class Test
{
private:
    int v;

public:
    Test(int h)
    {
        v = h;
    }
    int getV()
    {
        return v;
    }
    bool operator < (const Test& b) const
    {
        return v < b.v;
    }
};

int main()
{
    set <Test> st;
    for(int i = 1; i <= 10; i++)
    {
        Test t(i);
        st.insert(t);
    }

    for(set<Test>::iterator it = st.begin(); it != st.end(); it++)
    {
        cout << (*it).getV() << endl;
        //Test it2 = *it;
        //cout << it2.getV() << endl;
    }

    return 0;
}

将是

  

|错误:将'const Test'作为'int Test :: getV()'的'this'参数传递,丢弃限定符[-fpermissive] |

但如果我使用Test it2 = *it; cout << it2.getV() << endl;,它会很好用。为什么它使用'const Test'这个词以及为什么代码不能工作?

3 个答案:

答案 0 :(得分:6)

std::set迭代器返回const引用,因为set已排序,如果更改集合中对象的值,则它可能位于新值的错误位置。这可能会使对象无法找到并且更糟糕。

当你这样做时

Test it2 = *it;

您正在复制该对象,您可以根据需要修改该副本。你不能通过修改副本来搞乱set

问题是您的getV()方法没有正确的const限定。它应该是:

int getV() const
{
    return v;
}

然后第一个代码将编译并正常工作。

如果没有将const应用于正确的地方,通常会导致这类问题。你应该努力正确地应用const限定。

答案 1 :(得分:1)

set迭代器是一个const迭代器。您需要将getV()标记为常量(因为它不会更改对象,所以它应该是无论如何):

int getV() const // <--
{
    return v;
}

答案 2 :(得分:-3)

另一种方法是删除迭代器引用的对象的常量。在这种情况下,getV不需要是const方法。检查以下修改后的代码:

for(set<Test>::iterator it = st.begin(); it != st.end(); it++)
{
    cout << (const_cast<Test*>(&(*it)))->getV() << endl;
    //Test it2 = *it;
    //cout << it2.getV() << endl;
}

我不明白为什么上面的答案被低估了。我只是举了另一个例子。在某些情况下,我们必须这样做。有时我们需要在对象中设置一些值。下注选民能否看到下面这个例子的原因:

#include <iostream>
#include <set>
using namespace std;

class Test
{
private:
    int v;
    int w;

public:
    Test(int h, int i)
    {
        v = h;
        w = i;
    }
    int getV() const
    {
        return v;
    }
    int getW() const
    {
        return w;
    }

    void setW(int a) // This will not screw up the set as only v is used for comparison
    {
        w = a;
    }

    // Operator < is not using only v for comparison
    // of objects and not using w for that purpose
    bool operator < (const Test& b) const
    {
        return v < b.v;
    }
};

int main()
{
    set <Test> st;
    for(int i = 10; i >= 0; i--)
    {
        Test t(i, i);
        st.insert(t);
    }

    for(set<Test>::iterator it = st.begin(); it != st.end(); it++)
    {
        const_cast<Test*>(&(*it))->setW(1000);
    }


    for(set<Test>::iterator it = st.begin(); it != st.end(); it++)
    {
        cout << it->getV() << " " << it->getW() << endl;
    }
    return 0;
}