为什么函数 cleanup_str 必须用 'static' 关键字限定?

问题描述

我是 C++ 的新程序员。我遇到了一个问题,我无法理解这一点。你能帮我弄清楚吗?这是本书的一个例子,

class TextQuery {
public:
    using line_no = std::vector<std::string>::size_type;
    TextQuery(std::ifstream &);
    QueryResult query(const std::string &)  const;
private:
    std::shared_ptr<std::vector<std::string>> file;
    std::map<std::string,std::shared_ptr<std::set<line_no>>> wm;
    //static std::string cleanup_str(const std::string &); // the book example uses 'static'
    std::string cleanup_str(const std::string &); // I think 'static' key word is not needed.so i remove it.
};//class declearation ends here.

std::string TextQuery::cleanup_str(const std::string &word)  {
    string ret;
    for(auto it = word.begin();it != word.end();++it){
        if(!ispunct(*it))
            ret += tolower(*it);
    }
    return ret;
}

QueryResult TextQuery::query(const std::string &sought) const 
{
    static shared_ptr<set<line_no>> nodata(new set<line_no>);    //line 66
    auto loc = wm.find(cleanup_str(sought));                     //line 67

    if(loc == wm.end())
        return QueryResult(sought,nodata,file);
    else
    {
        return QueryResult(sought,loc->second,file);
    }  
}

我不能不规范删除“静态”关键字的版本与没有的版本之间的区别。编译错误是:

passing 'const TextQuery' as 'this' argument discards qualifiers [-fpermissive],67
the object has type qualifiers that are not compatible with the member function "TextQuery::cleanup_str" -- object type is: const TextQuery,67

我尝试了两种可以正常工作的方法

  1. 'static' 添加函数 cleanup_str。我无法理解为什么它可以通过。
  2. 我尝试的另一种方法是:删除函数 'const' 的最后一个 QueryResult TextQuery::query(const std::string &sought) const 关键字,使其变为: QueryResult TextQuery::query(const std::string &sought) 。这个方法有效,我也搞不懂这个原因。

解决方法

const 方法有一个约定——它不会改变类实例的内部状态。从技术上讲,它的实现方式是隐藏参数 this 具有类型 const TextQuery * - 指向 TextQuery 的常量(不可修改)对象的指针。要遵循该约定,您不能调用 非常量 方法,它可能会修改原始 const 方法的内部状态和制动约定。现在 -

在函数cleanup_str 中添加'static'。我不明白为什么它可以通过。

静态方法不适用于实例,它只属于那个类(它根本没有隐藏参数 this)因此从 const 方法调用这样的方法是安全的,合同不会被打破。如果您删除 static,那么该方法将成为常规的非 const 方法,并且从 const 调用它是不安全的。

我尝试的另一种方法是:删除函数 QueryResult 的最后一个 'const' 关键字

现在您的方法 query 变为非常量(this 的类型为 TextQuery *),因此可以安全地从中调用非常量或静态方法。所以你的编译器错误消失了。