3
#include <iostream>
#include <cmath>
using namespace std;

class Point
{
    protected:
        double x,y,z;
        double mag;
    public:
        Point(double a=0.0, double b=0.0, double c=0.0) : x(a), y(b), z(c)
        {
            mag = sqrt((x*x)+(y*y)+(z*z));
        }
        friend ostream& operator<<(ostream& os, const Point& point);
};

ostream& operator<<(ostream& os, const Point& point)
{
    os <<"("<<point.x<<", "<<point.y<<", "<<point.z<<") : "<<point.mag;
    return os;
}

class ePlane : public Point
{
    private:
        Point origin;
    public:
        static double distance(Point a, Point b);
        ePlane() : origin(0,0,0){}
};

double ePlane::distance(Point a, Point b) //does not compile
{
        return sqrt(pow((a.x-b.x),2)+pow((a.y-b.y),2)+pow((a.z-b.z),2));
}

int main()
{
    Point a(3,4,0);
    Point b(6,8,0);
    cout <<a<<endl;
    cout <<b<<endl;
    cout <<ePlane::distance(a,b)<<endl;
    return 0;
}

The above program does not compile when data members double x,y,z of class Point are declared protected. I do not understand why it does not compile, since protected members of base class should be accessible in derived class ePlane

I do not want to use a friend function to implement this, since protected members should already be accessible

Dost Arora
  • 355
  • 3
  • 12
  • Those are not protected members of the base class. Those are protected members of Point. If the parameters were ePlane parameters, they would be accessible. You can add `friend ePlane;` in Point, and you'll need to forward declare `class ePlane;`. – Eljay Apr 09 '18 at 12:45
  • Worth noting, you could write `a.*(&ePlane::x)` to replace `a.x` and likewise for others. Not recommended though – Passer By Apr 09 '18 at 13:06
  • @PasserBy Which only indicates, that this is pretty much a language standard bug: The members are accessible (via member pointer, no evil casting needed), but not via the direct route. I would always expect that something that is allowed, is allowed via the direct route. Anything else just serves to produce obfuscated code. But that's just my opinion on the topic... – cmaster - reinstate monica Apr 09 '18 at 13:22
  • @cmaster I'm inclined to believe the member pointer is the bug instead, it should never be allowed. `protected` means internal and shouldn't be used unless you are the object itself. Passing in a base class is a guarantee on its interface and not its internals, trying to access its internals is flawed logic. – Passer By Apr 09 '18 at 13:28
  • @PasserBy I see it the other way round: Code that is part of the derived class should have access to the protected members. I should be able to painlessly write an `operator ==()`, for instance, or other members that allow an object to interact with another objects of its own class. It's still well encapsulated, only code within the derived class hierarchy has access, the only difference is, that you are not forced to do horrible stuff like `a.*&ePlane::x` on one side. – cmaster - reinstate monica Apr 09 '18 at 13:44

1 Answers1

6

Let's say we have a class B, and a class D derived from B. The rule for protected access is not just:

"D can access protected members of B"

Instead, the rule is:

"D can access inherited protected members of B. In other words, D can access protected members of B which are within an object of type D (or derived from D)."

In your case, this means the parameters of distance would have to be typed as ePlane for distance to be able to access them.

Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455