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

age*_*ith 8 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:
        T m_value;
};
Run Code Online (Sandbox Code Playgroud)

为什么编译器不抱怨

    T& value() {return m_value;}
    T value() const {return m_value;}
Run Code Online (Sandbox Code Playgroud)

以及如何知道调用哪一个?

owa*_*der 13

这两个功能实际上并不相同.只有第二个函数被声明为const成员函数.如果调用成员的对象是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
}
Run Code Online (Sandbox Code Playgroud)

如果这两个功能被宣布为非const或者两者都宣称const,编译器(应该,反正)抱怨.


πάν*_*ῥεῖ 7

为什么编译器不抱怨

因为const计数不同的函数签名.你假设函数签名是相同的是错误的.
标记为的函数const将为任何const实例或引用调用Type<T>.

以及如何知道调用哪一个?

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;
};
Run Code Online (Sandbox Code Playgroud)
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();
}
Run Code Online (Sandbox Code Playgroud)

赋值运算符将调用非const版本.


const版本应该更好看

const T& value() const { 
     std::cout << "const version" << std endl;
     return m_value;
}
Run Code Online (Sandbox Code Playgroud)

因为您不能总是依赖RVO(返回值优化),并且可能会采用额外的副本(特别是对于较旧的编译器实现).


另请注意赋值运算符应返回对当前实例的引用:

 Type& operator=(const T& rhs) {value() = rhs; return *this;}
Run Code Online (Sandbox Code Playgroud)


Ser*_*eyA 5

关于功能解析优先级的几个词.编译器通过以下方式区分const /非const函数:

如果一个类只有const函数和给定的名称和参数列表,那么它将被调用为常量和非常量对象.在调用此函数之后,对象将"假定"constness(即使它不是const),这意味着该函数只能调用其他const函数.

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

如果一个类有两个可用的函数,const版本将用于const对象,非const版本将用于非const对象.

感谢@owacoder将我的注意力集中在描述中的初始混音上.

  • 我认为第二段中的逻辑是倒退的.对于`const`对象,不能调用非`constst`函数**. (3认同)