C++ C++;方法签名相同但返回类型不同

C++ C++;方法签名相同但返回类型不同,c++,templates,overloading,C++,Templates,Overloading,我看到了以下代码: template <class T> class Type { public: Type() {} T& operator=(const T& rhs) {value() = rhs; return value();} T& value() {return m_value;} T value() const {return m_value;} private:

我看到了以下代码:

template <class T>
class Type {
    public:
        Type() {}
        T& operator=(const T& rhs) {value() = rhs; return value();}
        T& value() {return m_value;}
        T value() const {return m_value;}
    private:
        T m_value;
};

那么如何知道调用了哪一个呢?

这两个函数实际上并不相同。只有第二个函数被声明为
const
成员函数。如果从中调用成员的对象是
const
,则使用后一个选项。如果对象为非常量,则使用第一个选项

例如:

void any_func(const Type *t)
{
    something = t->value(); //second `const` version used
}

void any_func2(Type *t)
{
    something = t->value(); //first non-`const` version used
}
如果两个函数都声明为non-
const
,或者都声明为
const
,编译器将(无论如何)抱怨

为什么编译器不抱怨

    T& value() {return m_value;}
    T value() const {return m_value;}
因为
常量
对不同的函数签名计数。您对函数签名相同的假设是错误的。
标记为
const
的函数将为
类型的任何
const
实例或引用调用

如何知道调用了哪一个

在函数中放入
cout
语句,并测试以下情况:

template <class T>
class Type {
    public:
        Type() {}
        T& operator=(const T& rhs) {value() = rhs; return value();}
        T& value() { 
            std::cout << "non const version" << std endl;
            return m_value;
        }
        T value() const { 
            std::cout << "const version" << std endl;
            return m_value;
        }
    private:
        T m_value;
};

关于函数解析优先级的几句话。编译器通过以下方式区分常量/非常量函数:

如果一个类只有具有给定名称和参数列表的const函数,它将被常量和非常量对象调用。调用此函数后,对象将“假定”常量(即使它不是常量),这意味着该函数只能调用其他常量函数

如果一个类只有非常量函数,它将被非常量对象调用。尝试为常量对象调用此函数将导致编译错误

如果一个类同时具有这两个函数,常量版本将用于常量对象,非常量版本将用于非常量对象


感谢@owacoder让我注意到描述中的初始混淆。

我认为第二段的逻辑是颠倒的。不能为
const
对象调用非
const
函数。@owacoder,我的错。你是对的,我误读了你的评论,错打了我的答案。将编辑它。是的,是的,是的@jaggedSpire是正确的,我只是略读,没有仔细阅读。这是罪过。在确定两个函数签名是否“相同”时,不要忽略关键字!
int main() {
    Type<int> t;
    t.value();

    Type<int> rt = t;
    rt.value();

    Type<int>* pt = &t;
    pt->value();

    const Type<int> ct;
    ct.value();

    const Type<int>& crt = t;
    crt.value();

    const Type<int>* pct = &t;
    pct->value();
}
const T& value() const { 
     std::cout << "const version" << std endl;
     return m_value;
}
 Type& operator=(const T& rhs) {value() = rhs; return *this;}