0

I have multiple classes that deal with some geometrical shape.

class Quad {
};

class Line {
};

Then, I have some classes that work on these shapes.

template< class Shape >
class Shape_Worker {
    virtual
    double
    work(
            Shape_Info< Shape >,
            Other_Class_That_Depends_On< Shape > ) = 0;
}

class Shape_Worker_Quad : public Shape_Worker< Quad > {
    double
    work(
            Shape_Info< Quad >,
            Other_Class_That_Depends_On< Quad > ) {
        // do something.
    }
};

My class shape info stores some coordinate information. A line has a single coordinate, a quadrilateral has two coordinates, and inherits from the line.

template< class Shape >
class Shape_Info {
};

template<>
class Shape_Info< Line > {
protected:
    double _r;
};

template<>
class Shape_Info< Quad > : public Shape_Info< Line > {
public:
    Shape_Info< Quad >::Shape_Info(
            const Shape_Info< Line > & abscissa_1,
            const Shape_Info< Line > & abscissa_2 )
        : Shape_Info< Line >( abscissa_1 )
        , _s( abscissa_2._r )
    {    
    }

protected:
    double _s;
};

When I compile this code, I get the following error in the Shape_Info< Quad > copy constructor:

double Shape_Info< Line >::_r is protected.

What am I doing wrong? Shape_Info< Quad > is derived from Shape_Info< Line >, so I do not understand why it does not inherit the _r variable. Did I overlook something? Or does it have to do with my template specialization?

I'm using GCC 4.8.2.

Any feedback is appreciated, thank you!

  • 1
    `protected` doesn't mean you can access the member from *any* instance of a base class, but only from your own base class subobject, via `this`. Add a copy constructor to `Shape_Info< Line >`, have `Shape_Info< Quad >` delegate to that, rather than accessing `abscissa._r` directly (which ain't gonna fly). – Igor Tandetnik Nov 25 '14 at 04:36
  • @IgorTandetnik nope, you can access protected members in any instance of your own class (not in a parent or sibling class). – n. m. could be an AI Nov 25 '14 at 04:41
  • Post your real code. This `Shape_Info< Quad >::Shape_Info( const Shape_Info< Quad > & abscissa ) : : abscissa._r , _s( abscissa._s )` makes no sense, with redundant qualification, two colons in a row and `abscissa._r` hanging in the air. – n. m. could be an AI Nov 25 '14 at 04:48
  • @n.m. Right. Now that I think of it, `: abscissa._r` part makes no sense, and doesn't seem to correspond to the compiler error. [In a simplified example](http://rextester.com/CSR15485), a different error message is produced. – Igor Tandetnik Nov 25 '14 at 04:49
  • So this is not related at all to my template specialization? But rather to the way protected works? – Hernan Villanueva Nov 25 '14 at 04:52
  • We have no idea because code you have posted is not code you have compiled. Prepare an [MCVE](http://stackoverflow.com/help/mcve). – n. m. could be an AI Nov 25 '14 at 04:55
  • Yes, I made a mistake. This should be corrected now. – Hernan Villanueva Nov 25 '14 at 04:59
  • You cannot access protected members in your parent class, only in objects of your own class. This is beaten to death everywhere. – n. m. could be an AI Nov 25 '14 at 05:02
  • Shape_Info< Line > has _r as a protected member. Shape_Info< Quad > is derived from Shape_Info< Line >. Should Shape_Info< Quad > have access to the members of Shape_Info< Line >? Could you expand, please? – Hernan Villanueva Nov 25 '14 at 05:07
  • The answer is no. Search "cannot access protected members" for more info. – n. m. could be an AI Nov 25 '14 at 05:15
  • Ok, I found this question: http://stackoverflow.com/questions/16785069/why-cant-a-derived-class-call-protected-member-function-in-this-code And I understand now. Any suggestions on how I may improve my design? – Hernan Villanueva Nov 25 '14 at 05:16
  • Either make _r and _s public? Or simply get rid of that constructor? – Hernan Villanueva Nov 25 '14 at 05:19
  • Try a protected constructor in the base class. – n. m. could be an AI Nov 25 '14 at 05:23

1 Answers1

0

Just to describe the problem: you only have access to protected members of objects of the same class. If you get an object of a base class (or a pointer or reference to it) you do not have access to its protected members! A simpler example replicating the same issue is this:

class Base {
protected:
    Base(int member): member(member) {}
    int member;
};
class Derived: public Base {
public:
    Derived(Base const& b): Base(b.member) {} // illegal: no access to `b.member`
    Derived(Derived const& d): Base(d.member) {} // OK: d is of type Derived
};

To fix your problem, you'll need a suitable way to access _r, probably by providing a public accessor.

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
  • There is about a zillion duplicate questions out there. – n. m. could be an AI Nov 25 '14 at 05:32
  • Yes, there are several duplicate questions out there. However, I failed to identify my problem. You can't get the right answers without asking the right questions. At first I thought my issue was related to my template specialization; it's my first time working with them so my assumption was that I had made a mistake there. I now understand that the real issue was the incorrect use of protected member variables. – Hernan Villanueva Nov 25 '14 at 17:19
  • @user199150: Well, n.m. was telling me off for answering the question instead of marking it as a duplicate. He only told me off mildly, i.e., with a comment rather than a downvote. – Dietmar Kühl Nov 25 '14 at 19:53