【问题标题】:Overloading operators in derived class派生类中的重载运算符
【发布时间】:2011-08-06 10:48:00
【问题描述】:

如果我需要在派生类中使用它们,我是否必须重新定义所有具有派生类型的重载运算符?

以下代码编译良好:

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++ Primer 4th Ed. 第 15.5.3 节。

如果派生类想要通过其类型使所有重载版本可用,那么它必须重新定义所有这些版本,或者一个都不重新定义。

引用“none of them”的部分在这里有意义吗?

【问题讨论】:

    标签: c++ operator-overloading


    【解决方案1】:

    Overloading operators in derived class from IBM.

    类 A 中名为 f 的成员函数 将隐藏所有其他名为 f 的成员 A的基类,不管 返回类型或参数。这 下面的例子证明了这一点:

    struct A {
      void f() { }
    };
    
    struct B : A {
      void f(int) { }
    };
    
    int main() {
      B obj_B;
      obj_B.f(3);
    //  obj_B.f();
    }
    

    编译器不允许 函数调用 obj_B.f() 因为 void B::f(int) 的声明有 隐藏 A::f()。

    重载而不是隐藏 基类 A 在 a 中的函数 派生类B,你介绍 函数名进入作用域 B 带有 using 声明。这 以下示例与 前面的例子,除了 using 使用 A::f: 声明

    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();
    }
    

    所以如果你不全部重载,那么只会使用重载的函数。

    【讨论】:

    • 嘿,你觉得可以引用这么多别人的内容吗?对我来说似乎是版权问题。
    • @Ernest:我没有创建 C++ 语言,所以我必须参考一些东西。看到这个类似的元问题:meta.stackexchange.com/questions/46448/…
    • +1 以获得正确的解决方案。由于您链接到原始内容,因此您可以使这篇文章更短。
    • @Andre:我在防止链接失效。
    • 请缩短此报价
    【解决方案2】:

    这意味着如果Point 有多个operator+(),而您只重新定义了其中一个,那么在派生类中只能访问那个;其他重载将被隐藏。如果你在派生类中声明no operator+(),那么所有的父类都可用;如果您在派生类中声明 any,则 none 的父类可用。

    有意义吗?这种情况很好:父母声明了一个,然后你重新定义了那个。没问题。但是,如果父类声明了两个,那么只声明一个的子类将只能访问那个。

    【讨论】:

    • @Ernest Friedman-Hill: 1. Override 仅适用于虚函数,本例为overloading 2. 成员被继承但hidden 因为派生类重载。
    • 是的,这都是正确的。我的语言非常不精确,而且带有 Java 色彩。我会补上的。
    • @Ernest Friedman-Hill:抱歉,在你重新格式化之前我已经发布了答案,否则我会避免。
    • 同一个类怎么会有多个成员函数operator+()?
    • @Dave18:除了 const Point& 之外,您还可以有许多其他类型的重载。在这种特殊情况下可能没有意义,但某些类可能会发现重载 operator+ 对字符串、int、double 等很有用...
    【解决方案3】:

    在 C++ 中,没有跨作用域的重载,派生类作用域也不例外。

    Derived 和 Base 类之间没有重载决议。一个例子:

    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;
    }
    

    输出是:

    D::func1()3.3
    D::func1()3.6
    

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

    所以在您的代码示例中,如果Point 有多个operator+(),并且您在派生类中重新定义了相同的运算符,那么派生类的对象只能访问该派生类运算符,因为该版本的函数@ 987654325@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 这三个术语有时会误用,但它们都有不同的含义。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-20
      • 1970-01-01
      相关资源
      最近更新 更多