关于c ++:在派生类中重载运算符

Overloading operators in derived class

如果需要在派生类中使用重载运算符,是否需要用派生类型重新定义所有重载运算符?

以下代码编译良好:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class Point {

public:

    Point(int X = 0, int Y = 0):x(X), y(Y) {}

    virtual ~Point() {}

    Point operator +(Point &rhs) {
        return Point(x + rhs.x, y + rhs.y);
    }

protected:
    int x, y;
};

class Vector : public Point {

public:

    Vector(int X, int Y) : Point(X, Y) {}

    ~Vector() {}

    Vector operator +(Vector &rhs) {
        return Vector(x + rhs.x, y + rhs.y);
    }
};

int main()
{
    Vector v1(1, 2);
    Vector v2(3, 2);

    Vector v3 = v2 + v1;
}

但根据我读到的,

C++引物第四版,第155.3节。

If a derived class wants to make all
the overloaded versions available
through its type, then it must either
redefine all of them or none of them.

这里引用的"EDOCX1"〔0〕部分有什么意义吗?


这意味着,如果Point有多个operator+(),并且您只重新定义了其中一个,那么在派生类中只能访问一个;其他重载将隐藏。如果在派生类中没有声明operator+(),则所有父类都可用;如果在派生类中声明了任何父类,则所有父类都不可用。

有道理?这种情况很好:父级声明了一个,而您重新定义了那个。没问题。但是,如果父类声明了两个,那么只有声明一个的子类将只能访问该类。


从IBM派生类中重载运算符。

A member function named f in a class A
will hide all other members named f in
the base classes of A, regardless of
return types or arguments. The
following example demonstrates this:

1
2
3
4
5
6
7
8
9
10
11
12
13
struct A {
  void f() { }
};

struct B : A {
  void f(int) { }
};

int main() {
  B obj_B;
  obj_B.f(3);
//  obj_B.f();
}

The compiler would not allow the
function call obj_B.f() because the
declaration of void B::f(int) has
hidden A::f().

To overload, rather than hide, a
function of a base class A in a
derived class B, you introduce the
name of the function into the scope of
B with a using declaration. The
following example is the same as the
previous example except for the using
declaration using A::f:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
struct A {
  void f() { }
};

struct B : A {
  using A::f;
  void f(int) { }
};

int main() {
  B obj_B;
  obj_B.f(3);
  obj_B.f();
}

因此,如果不重载所有函数,那么只使用重载函数。


在C++中,跨范围派生类的重载并不属于此一般规则的例外。

派生类和基类之间没有重载解析。一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class B
{
    public:
    int func1(int i)
    {
        cout<<"B::func1()";
        return i+1;
    }
};



class D : public B
{
    public:
    double func1(double d)
    {
        cout<<"D::func1()";
        return d+1.3;
    }
};

int main ()
{
    D *pd = new D;

    cout << pd->func1(2)  <<endl;
    cout << pd->func1(2.3)<<endl;

    return 0;
}

输出是:

1
2
D::func1()3.3
D::func1()3.6

同样的规则也适用于运算符成员函数,毕竟它们也是成员函数!

所以在代码示例中,如果Point有多个operator+(),并且在派生类中重新定义了相同的运算符,那么只有派生类的对象才能访问该派生类的对象,因为函数hides的版本是operator+()的其他基类版本。如果不在派生类中重新定义operator+(),那么operator+()的父类版本都不会被隐藏,因此无法通过派生类的对象访问。

因此,声明:If a derived class wants to make all the overloaded versions available through its type, then it must either redefine all of them or none of them.

另外,请注意,overloadingoverridingfunction hiding是三个术语,它们有时被随意误用,但它们都有各自的含义。