Method chaining + inheritance don't play well together?

后端 未结 15 810
北荒
北荒 2020-12-08 22:20

Consider:

// member data omitted for brevity

// assume that \"setAngle\" needs to be implemented separately
// in Label and Image, and that Button does need         


        
15条回答
  •  暗喜
    暗喜 (楼主)
    2020-12-08 22:56

    C++ does support return value covariance on virtual methods. So you could get something like what you want with a little work:

    #include 
    using std::string;
    
    // member data omitted for brevity
    
    // assume that "setAngle" needs to be implemented separately
    // in Label and Image, and that Button does need to inherit
    // Label, rather than, say, contain one (etc)
    
    
    struct Point
    {
        Point() : x(0), y(0) {};
        Point( int x1, int y1) : x( x1), y( y1) {};
    
        int x;
        int y;
    };
    
    struct Widget {
        virtual Widget& move(Point newPos) { pos = newPos; return *this; }
        virtual ~Widget() {};
    
        Point pos;
    };
    
    struct Label : Widget {
        virtual ~Label() {};
        virtual Label& move( Point newPos) { Widget::move( newPos); return *this; }
    
        // made settext() virtual, as it seems like something 
        // you might want to be able to override
        // even though you aren't just yet
        virtual Label& setText(string const& newText) { text = newText; return *this; }
        virtual Label& setAngle(double newAngle) { angle = newAngle; return *this; }
    
        string text;
        double angle;
    };
    
    struct Button : Label {
        virtual ~Button() {};
        virtual Button& move( Point newPos) { Label::move( newPos); return *this; }
        virtual Button& setAngle(double newAngle) {
            //backgroundImage.setAngle(newAngle);
            Label::setAngle(newAngle);
            return *this;
        }
    };
    
    int main()
    {
        Button btn;
    
        // this works now
        btn.move(Point(0,0)).setText("Hey");
    
        // this works now, too
        btn.setText("Boo").setAngle(.5); 
    
      return 0;
    }
    

    Note that you should use virtual methods for doing something like this. If they aren't virtual methods, then the 'reimplemented' methods will result in name-hiding and the method called will depend on the static type of the variable, pointer or reference so it might not be he correct method if a base pointer or reference is being used.

提交回复
热议问题