|
|
int
)的不同变量被应用了加法运算符,然后是赋值运算符。对于基本的算术类型,这类操作的含义通常是显而易见且无歧义的,但对于某些类类型可能并非如此。例如:
|
|
b
和 c
进行加法运算的结果并不明显。实际上,仅这段代码就会导致编译错误,因为 myclass
类型没有为加法定义任何行为。然而,C++ 允许大多数运算符被重载,以便可以为几乎任何类型(包括类)定义其行为。以下是可以被重载的所有运算符的列表:可重载的运算符 |
---|
|
operator
函数进行重载,这些函数是具有特殊名称的常规函数:它们的名称以 operator
关键字开头,后跟被重载的*运算符符号*。语法是:type operator sign (parameters) { /*... 函数体 ...*/ }
x
和 y
。两个*笛卡尔向量*的加法运算定义为它们的 x
坐标相加,以及它们的 y
坐标相加。例如,将*笛卡尔向量* (3,1)
和 (1,2)
相加会得到 (3+1,1+2) = (4,3)
。这可以用 C++ 实现如下代码:
|
|
4,3 |
CVector
的出现感到困惑,请注意其中一些指的是类名(即类型)CVector
,而另一些是同名函数(即构造函数,其名称必须与类名相同)。例如:
|
|
CVector
类的函数 operator+
重载了该类型的加法运算符(+
)。一旦声明,这个函数就可以通过运算符隐式调用,或者通过其函数名显式调用:
|
|
operator+
实际上执行减法,或者重载 operator==
来用零填充对象,这在语法上是完全有效的,尽管使用这样的类可能会很有挑战性。operator+
这样的操作,成员函数重载所期望的参数自然是运算符右侧的操作数。这对于所有二元运算符(即左侧有一个操作数,右侧也有一个操作数的运算符)都是通用的。但是运算符可以有多种形式。下表总结了每种可重载的不同运算符所需的参数(请将每种情况下的 @
替换为相应的运算符):表达式 | 运算符 | 成员函数 | 非成员函数 |
---|---|---|---|
@a | + - * & ! ~ ++ -- | A::operator@() | operator@(A) |
a@ | ++ -- | A::operator@(int) | operator@(A,int) |
a@b | + - * / % ^ & | < > == != <= >= << >> && || , | A::operator@(B) | operator@(A,B) |
a@b | = += -= *= /= %= ^= &= |= <<= >>= [] | A::operator@(B) | - |
a(b,c...) | () | A::operator()(B,C...) | - |
a->b | -> | A::operator->() | - |
(TYPE) a | TYPE | A::operator TYPE() | - |
a
是 A
类的对象,b
是 B
类的对象,c
是 C
类的对象。TYPE
是任意类型(该运算符重载了到 TYPE
类型的转换)。operator+
示例中使用。但某些运算符也可以作为非成员函数重载;在这种情况下,运算符函数将相应类的对象作为其第一个参数。
|
|
4,3 |
this
代表一个指向其成员函数正在被执行的对象的指针。它在类的成员函数内部使用,以引用对象本身。
|
|
yes, &a is b |
operator=
成员函数中。继续看前面*笛卡尔向量*的例子,它的 operator=
函数可以这样定义:
|
|
operator=
隐式生成的代码非常相似。
|
|
6 7 |
|
|
|
|
Dummy
类中所有对象共享的静态变量 n
。this
。const
对象时:
|
|
const
。但请注意,构造函数仍然会被调用,并被允许初始化和修改这些数据成员:
|
|
10 |
const
对象的成员函数只有在它们本身被指定为 const
成员时才能被调用;在上面的例子中,成员函数 get
(没有被指定为 const
)不能从 foo
调用。要将一个成员函数指定为 const
成员,const
关键字应紧跟在函数原型参数的右括号之后:
|
|
const
可以用来限定成员函数返回的类型。这个 const
与指定成员为 const
的那个不同。两者是独立的,并位于函数原型中的不同位置:
|
|
const
的成员函数不能修改非静态数据成员,也不能调用其他非 const
成员函数。本质上,const
成员不应修改对象的状态。const
对象只能访问标记为 const
的成员函数,但非 const
对象不受限制,因此可以访问 const
和非 const
成员函数。const
对象,因此把所有不修改对象的成员标记为 const 是不值得的,但实际上 const 对象非常普遍。大多数接受类作为参数的函数实际上是通过 const
引用来接受它们的,因此,这些函数只能访问它们的 const
成员:
|
|
10 |
get
没有被指定为 const
成员,那么在 print
函数中调用 arg.get()
是不可能的,因为 const
对象只能访问 const
成员函数。const
而另一个不是。在这种情况下,当对象本身是 const 时,调用 const
版本;当对象本身是非 const
时,调用非 const
版本。
|
|
15 20 |
|
|
int
的整数值 115 和 36,我们会这样写:
|
|
|
|
template <...>
前缀开头:
|
|
100 |
getmax
定义的语法:
|
|
T
搞糊涂了吗?这个声明中有三个 T
:第一个是模板参数。第二个 T
指的是函数返回的类型。第三个 T
(尖括号中的那个)也是必需的:它指定了这个函数的模板参数也是类模板的参数。mycontainer
,它可以存储任何类型的一个元素,并且只有一个名为 increase
的成员函数,该函数会增加其值。但我们发现,当它存储一个 char
类型的元素时,拥有一个带有 uppercase
成员函数的完全不同的实现会更方便,所以我们决定为该类型声明一个类模板特化:
|
|
8 J |
|
|
template<>
,包含一个空的参数列表。这是因为所有类型都是已知的,这个特化不需要模板参数,但它仍然是类模板的一个特化,因此需要这样标记。<char>
特化参数。这个特化参数本身标识了模板类被特化的类型(char
)。注意通用类模板和特化之间的区别:
|
|
![]() 类 (I) | ![]() 目录 | ![]() 特殊成员 |