C++ 为什么运算符[]有两种定义?

C++ 为什么运算符[]有两种定义?,c++,operators,operator-overloading,constants,C++,Operators,Operator Overloading,Constants,我目前正在研究我的数据结构类的资料,这涉及到一个练习,我们试图定义一个模仿向量的类,这样我们就可以了解引擎盖下面发生了什么。一切都有意义,直到我意识到操作符[]有两种定义。在这方面: typedef unsigned int size_type; T& operator[] (size_type i) { return m_data[i]; } const T& operator[] (size_type i) const { return m_data[i]; } 第一个问题

我目前正在研究我的数据结构类的资料,这涉及到一个练习,我们试图定义一个模仿向量的类,这样我们就可以了解引擎盖下面发生了什么。一切都有意义,直到我意识到
操作符[]
有两种定义。在这方面:

typedef unsigned int size_type;
T& operator[] (size_type i) { return m_data[i]; }
const T& operator[] (size_type i) const { return m_data[i]; }
第一个问题:为什么必须有两个
运算符[]
的定义

第二个问题:为什么这不会引发多定义错误

抱歉,如果有任何模糊或明显的地方。我是C++新手,我唯一的体验是java。谢谢

为什么必须有两个运算符[]的定义?

如果您想要一个可以修改其值(例如,
obj[i]=value
),而另一个不能(使用
const

为什么这不会引发多定义错误?

基于$9.3.1/3州-

非静态成员函数可以声明为const、volatile或const volatile。这些限定符影响此指针的类型(9.3.2)。它们还影响函数类型(8.3.5)声明为常量的成员函数是常量成员函数,声明为volatile的成员函数是volatile成员函数,声明为const volatile的成员函数是const volatile成员函数。”

也就是说,您可以使用这些限定符之一来重载函数,例如:

void func();
void func() const;

这是一个常见的C++模式。

const
成员函数(即原型后带有关键字
const
的函数)在
*此
const
时适用;换句话说,如果它与
const
对象一起使用。由于
*此
是常量,因此可以合理地假设它无法修改,因此
运算符[]
必须返回常量引用

另一个成员函数将应用于任何对象,但由于它不如
常量
函数具体,因此仅当
*此
不是
常量
时才适用。在这种情况下,可能会修改返回的引用(
object[3]=new_value;
),因此返回类型不是
const

第一个问题:为什么必须有两个定义 操作员[]

这些定义因其常量限定符(和结果类型)而异。其中之一是const,它返回对内部数据的const引用。如果您的容器声明为const,则使用它,因此对其内容的引用也是const。如果contianer不是常量,则使用非常量运算符,以便修改内部数据

第二个问题:为什么这不会引发多定义错误


因为常量限定符是函数原型的一部分,这意味着
void foo()
void foo()常量实际上是两种不同的方法。它允许基于对象的const限定符重载调用方法。

< p>每个函数都可以被你所称的“代码>签名< /代码>所识别,当你在代码< >声明/COD> C++中的函数时,你可以写函数的签名,签名看起来像

qualifiers T ( qualifiers U u ) qualifiers;
############ ------------------ ::::::::::
签名由我用
-
概括的两部分组成,
部分是返回类型,
-
部分是函数接受的参数的描述

关键是,如果您使用不同的
限定符编写相同的签名,
C++
仍然认为这是对相同函数的重新声明/重新定义,因此,
限定符
是签名的一部分,但是当比较具有相同名称的函数的多个声明/定义时,编译器实际上会删除它们

你应该阅读更多关于限定符的内容,我在这里简化了这个概念

您还可以在签名后添加更多限定符(第一部分用
概括),以声明有关函数工作方式的一些属性,例如
const
意味着您声明函数不修改它可以访问的变量