0

It looks like it is not possible to access a protected member through a shared_ptr. Here is a minimal example that doesn't compile:

// compile with g++ -std=c++11 protect.cpp

#include <iostream>
#include <memory>

class C
{
   public:
      C(int xval = 0) : x(xval) {}

   protected:
      int x = 0;
};

class D : public C
{
   public:
      D(int xval = 0) : C(xval) {}
      void print_sum( const std::shared_ptr<C>& other );
};

void D::print_sum( const std::shared_ptr<C>& other )
{
   int sum = x + other->x;
   std::cout << "the sum is " << sum << std::endl;
}

int main( int argc, char** argv, char** envp)
{
   std::shared_ptr<C> first = std::make_shared<C>(2);
   std::shared_ptr<D> second = std::make_shared<D>(3);

   second->print_sum( first );
   return 0;
}

And here are the specific error messages I get:

$ g++ -std=c++11 protect.cpp
protect.cpp: In member function ‘void D::print_sum(const std::shared_ptr<C>&)’:
protect.cpp:13:15: error: ‘int C::x’ is protected
       int x = 0;
               ^
protect.cpp:25:25: error: within this context
    int sum = x + other->x;

It seems strange that D doesn't have access to x even though D is derived from C, and I always thought a derived class could use protected base class members.

This problem isn't really a show-stopper for me; in my use case, C and D are going to be implemented as part of the same patch set, so it's easy enough to just make x public as a workaround. But is there a more "idiomatic" way to make this code work?

Just in case this is a gcc bug, here are the versions I'm using:

$ cat /etc/issue
Ubuntu 14.04.3 LTS \n \l

$ g++ --version
g++ (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Praetorian
  • 106,671
  • 19
  • 240
  • 328
  • call a friend (wink wink) – bolov Nov 03 '15 at 17:58
  • 2
    This has [nothing to do](http://coliru.stacked-crooked.com/a/b78ca8c19fe87a8a) with `shared_ptr`. `D` can only access inherited protected members via a `D` instance. – Praetorian Nov 03 '15 at 18:13
  • Until the last year or so, most of my OO programming has been in Java...I just assumed `protected` would have a similar meaning in C++ as in Java, but apparently in C++ it means "allow access to all parent classes" whereas in Java it means "allow access to all derived classes". I've also done ton of programming in Python which leads me to naturally tend to just give up on access specifiers and make everything public, which this experience just seems to reinforce... – theoreticalbts Nov 03 '15 at 18:45

1 Answers1

2

Quote from this SO answer:

You can only access protected members in instances of your type (or derived from your type). You cannot access protected members of an instance of a parent or cousin type.

Which means that from D you can access only this->x or d.x (where d is another object of type D), not c.x even if c is an object of type C.

The fix is to declare D as a friend of C:

class D; // forward declare D
class C
{
   public:
      C(int xval = 0) : x(xval) {}

      friend class D; // <--
   protected:
      int x = 0;

};

or get the parameter as C, not as D:

// no need for any friend declaration for this
void print_sum( const std::shared_ptr<D>& other ); 

btw, this has nothing to do with shared pointer.

Community
  • 1
  • 1
bolov
  • 72,283
  • 15
  • 145
  • 224