我目前正在处理来自我的数据结构课程的材料,其中涉及一个练习,我们尝试定义一个模仿矢量的类,这样我们就可以了解底层发生了什么。在我意识到operator[]
有两个定义之前,一切都有意义。在上下文中:
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]; }
第一个问题:为什么有必要对operator[]
进行两种定义?
第二个问题:为什么这不会引发多重定义错误?
对不起,如果有什么含糊不清或似乎很明显。我是C ++的新手,我唯一的另一个经验是使用Java。谢谢!
答案 0 :(得分:2)
为什么必须有两个operator []的定义?
如果您想要一个可以修改其值的文件(例如obj[i] = value
)而另一个不能修改(const
),则必须这样做。
为什么这不会引发多重定义错误?
基于 $ 9.3.1 / 3州 -
"非静态成员函数可以声明为const,volatile或const volatile。 这些cvqualifiers会影响this指针的类型(9.3.2)。它们还影响成员函数的函数类型(8.3.5); 声明const的成员函数是const成员函数,声明volatile的成员函数是volatile成员函数,声明const volatile的成员函数是const volatile成员函数。"
也就是说,您可以使用其中一个限定符来重载函数,例如:
void func();
void func() const;
答案 1 :(得分:2)
这是一种常见的C ++模式。
当const
为const
时,*this
成员函数(即原型后的关键字const
的成员函数)适用;换句话说,如果它与const
对象一起使用。由于*this
是常量,因此假设无法修改它是合理的,因此operator[]
必须返回一个const引用。
其他成员函数将应用于任何对象,但由于它不具有const
特定对象,因此仅当*this
不是const
时才适用。在这种情况下,可能会修改返回的引用(object[3] = new_value;
),因此返回类型不是const
。
答案 2 :(得分:2)
第一个问题:为什么有必要有两个定义 运算符[]
这些定义与const限定符(和结果类型)不同。其中一个是const并返回对内部数据的const引用。如果您的容器被声明为const,则使用它,因此对它的内容的引用也是const。如果您的contianer不是const,则使用非const运算符,以便可以修改内部数据。
第二个问题:为什么不抛出多重定义错误?
因为const-qualifier是函数原型的一部分,这意味着void foo();
和void foo() const;
实际上是两种不同的方法。它允许基于用于调用方法的对象的const限定符进行重载。
答案 3 :(得分:0)
每个函数都可以通过你可以调用的signature
来识别,当你在C ++函数中declare
编写函数的签名时,签名看起来像
qualifiers T ( qualifiers U u ) qualifiers;
############ ------------------ ::::::::::
因此签名由我用#
和-
概述的2部分组成,#
部分是返回类型,部分{{1是函数接受的参数的描述。
关键在于,如果您使用不同的-
编写相同的签名,qualifiers
仍然认为这是同一函数的重新声明/重新定义,因此C++
是其中的一部分签名但当比较具有相同名称的函数的多个声明/定义时,它们实际上被编译器删除。
你应该阅读更多关于限定词的内容,我在这里简化了这个概念。
您还可以在签名后添加更多限定符(我使用qualifiers
概述的部分),以声明有关函数工作方式的一些属性,例如:
表示您声明您的函数没有& #39; t修改它可以访问的变量。