【问题标题】:How does overloading of const and non-const functions work?const 和非常量函数的重载是如何工作的?
【发布时间】:2011-07-03 11:27:57
【问题描述】:

STL 充满了这样的定义:

iterator begin ();
const_iterator begin () const;

由于返回值不参与重载决议,这里唯一的区别是函数是const。这是重载机制的一部分吗?什么是编译器的算法来解决这样的行:

vector<int>::const_iterator it = myvector.begin();

【问题讨论】:

    标签: c++ function stl constants overloading


    【解决方案1】:

    编译器的“算法”是这样的: X 类的每个成员函数都有一个 X& 类型的隐式参数(我知道,大多数人认为它是 X*,但标准规定,出于重载解决方案的目的,我们假设它是一个引用)。对于 const 函数,参数的类型是 const X&。因此,如果一个成员函数被称为两个版本,const 和 non-const,则该算法都是可行的候选者,并且就像在重载决议的其他情况下一样选择最佳匹配。没有魔法:)

    【讨论】:

    • 谢谢,这很有用,但是我的问题是(错误)假设调用 const 变体是因为它分配给的变量的类型。 @awoodland 解释了这一点
    • 为什么引用而不是指针,这也只是为了解决重载问题,有什么不明显的原因吗?
    【解决方案2】:

    在你给出的例子中:

    vector<int>::const_iterator it = myvector.begin();
    

    如果 myvector 不是 const,则将调用 begin() 的非 const 版本,您将依赖从迭代器到 const_iterator 的隐式转换。

    【讨论】:

      【解决方案3】:

      是的,const 修饰符会影响重载。如果myvectorconst,此时将调用const 版本:

      void stuff( const vector<int>& myvector )
      {
          vector<int>::const_iterator it = myvector.begin(); //const version will be called
      }
      
      vector<int> myvector;    
      vector<int>::const_iterator it = myvector.begin(); //non-const version will be called
      

      【讨论】:

        【解决方案4】:

        来自 C++ 标准(第 13.3.1 节候选函数和参数列表):

        For non-static member functions, the type of the implicit object parameter is “reference to cv X” where X is the class of which the function is a member and cv is the cv-qualification on the member function declaration. [Example: for a const member function of class X, the extra parameter is assumed to have type “reference to const X”. ]

        因此,在您的情况下,如果 myvector 对象是 const 编译器将选择具有 reference to const vector 类型的隐式对象参数的 begin 版本,这是 begin 的 const 版本。

        【讨论】:

          【解决方案5】:

          值得一提的是,c++允许 const 方法/函数重载(例如 foo() const),但不允许 const arguments 重载(例如 bar(int a) 和 bar (const int a))。

          【讨论】:

            【解决方案6】:

            编译器在编译时判断对象变量是否为const

            然后它选择相应的重载,以及它具有的任何返回类型。

            class C {
                public:
                    int f() { return 1; }
                    float f() const { return 1.5; }
            };
            
            // Non const.
            C c;
            assert(c.f() == 1);
            
            // Convert variable const at compile time.
            assert(const_cast<const C&>(c).f() == 1.5);
            
            // Same as above but with an explicit reference.
            const C& d = c;
            assert(d.f() == 1.5);
            
            // Analogous but with a new const object from the start.
            const C e;
            assert(d.f() == 1.5);
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2019-07-09
              • 2014-11-19
              • 1970-01-01
              相关资源
              最近更新 更多