0

If I have two classes: one is Point and the second is Square, Point has member data: x and y those are "private" to represent the coordinates of the point.

The class Square and similar ones implement the "has-a" relationship; so for example Square has four Points. For some reason Point grants access to its private data through "friendship"; but only to a member function called print of the containing classes.

The problem:

The class Point needs to see the definition of the classes like Square so that it declares their print member as a friend.

Square needs to see the definition of class Point so that it can declare instances of it as its members.

Using forward-declaration won't solve the issue because the fact that it is still "incomplete type". So how it could be solved?

class Square;
class Point{
    public:
        using pos = int;

        Point() = default;
        Point(pos, pos);

        pos getX()const{ return x_; }
        pos getY()const{ return y_; }
        void setX(pos x){ x_ = x; }
        void setY(pos y){ y_ = y; }

    private:
        pos x_{};
        pos y_{};

        // friend void Square::print()const; // the problem here. Square is still incomplete type
        // friend class Square; // we don't want this solution
};

inline Point::Point(pos x, pos y) :
    x_{ x },
    y_{ y }{

}

class Square{
    public:
        Square(const Point&, const Point&, const Point&, const Point&);

        Point getPtA()const{ return ptA_; }
        Point getPtB()const{ return ptB_; }
        Point getPtC()const{ return ptC_; }
        Point getPtD()const{ return ptD_; }
        void setPtA(const Point& ptA){ ptA_ = ptA; }
        void setPtB(const Point& ptB){ ptB_ = ptB; }
        void setPtC(const Point& ptC){ ptC_ = ptC; }
        void setPtD(const Point& ptD){ ptD_ = ptD; }

        void print()const;

    private:
        Point ptA_, ptB_, ptC_, ptD_;
};

Square::Square(const Point& ptA, const Point& ptB, const Point& ptC, const Point& ptD) :
    ptA_{ ptA }, ptB_{ ptB },
    ptC_{ ptC }, ptD_{ ptD }{

}

void Square::print()const{
    using pos = Point::pos;

    for(pos i{ptA_.x_}; i != ptB_.x_; ++i){
        for(pos j{ptA_.y_}; j != ptC_.y_; ++j)
            std::cout << "*";
        std::cout << std::endl;
    }
}
Syfu_H
  • 605
  • 4
  • 17
  • 4
    A point has no constraints on its values. It's just two numbers. Going full "OO" on it with getters and setters is an exercise in obfuscation. You "abstract" two values that can be altered publicly from anywhere outside the class, so it's pointless. A simple structure with two public member variables will do the same and be far easier to work with. – StoryTeller - Unslander Monica May 11 '19 at 16:06
  • @StoryTeller: I agree with you. But the thing may occur in other situations. – Syfu_H May 11 '19 at 16:12
  • 2
    @Syfu_H blindly doing OO and encapsulation for the sake of encapsulation can also be the wrong choice in other situations ;). Seriously, I find it difficult to see the actual aim of this exercise, mutual dependency is always a design smell, you better fix the design, but it seems you already agree that this isnt a sound design for `Square` and `Point`... – 463035818_is_not_an_ai May 11 '19 at 16:16
  • why do you need the `friend`s ? Cant you call the getters? – 463035818_is_not_an_ai May 11 '19 at 16:20
  • 1
    If this is an academical question then: Just dont do it. The problem appears to be purely self-made. Either dont use `friend` but getters or dont encapsulate what you dont want to have encapsulated. If you have a real problem at hand then please tell us about that (see also [xy problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)) – 463035818_is_not_an_ai May 11 '19 at 16:32
  • Why not just have `Point` provide it's own public `print()` function. Then `Square::print()` only needs to print the set of points in order, without worrying about accessing the data. No need for friendship at all – Peter May 11 '19 at 18:26

0 Answers0