0

I thought that protected members in a base class are accessible from a derived class, but not so:

template <typename T>
class SharedPointer
{
protected:
    explicit SharedPointer(T* const ptr) : ptr(ptr) {}

public:
    constexpr SharedPointer() : ptr(nullptr) { }

protected:
    T* ptr; 
};

template <typename T>
class WeakPointer : public SharedPointer<T>
{
protected:
    using parent_t = SharedPointer<T>;
    WeakPointer(T* ptr) : parent_t(ptr) {   }
public:
    WeakPointer(const WeakPointer& other)
    {
    }
    WeakPointer(WeakPointer&& other) = delete;
    WeakPointer(const SharedPointer<T>& other)
    {
        this->ptr = other.ptr;
    }    
};    

int main()
{
    SharedPointer<int> sp;
    WeakPointer<int> wp = sp;
}

The error I get is:

'SharedPointer<int>::ptr': cannot access protected member declared in class 'SharedPointer<int>'

What is the problem here?

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Zebrafish
  • 11,682
  • 3
  • 43
  • 119

1 Answers1

4

Sometimes protected is not that intiutive. From Access specifiers on cppreference:

A protected member of a class is only accessible

  1. to the members and friends of that class;
  2. to the members of any derived class of that class, but only when the class of the object through which the protected member is accessed is that derived class or a derived class of that derived class:

And then follows an example.

In your case, 2) means that WeakPointer<T> can only acces ptr via a WeakPointer<T> object. If it could access ptr through a reference to a SharedPointer<T> then it could access ptr of a different derived class. And that's what the rules are made to avoid.


In this particular case, you do not actually need to access ptr in the derived class:

WeakPointer(const SharedPointer<T>& other) : SharedPointer<T>(other)
{}

Live Demo

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
  • What's the best way to handle this? – Zebrafish Jan 13 '23 at 22:28
  • The first thought that came to mind was using a member initializer list to copy-construct the `SharedPointer` base class. But it kind of raises the question of whether it actually makes sense for `WeakPointer` to inherit from `SharedPointer` to begin with. – Nathan Pierson Jan 13 '23 at 22:31
  • @NathanPierson my idea too and then I didnt bother to think more :P Not sure if it actually makes sense. Compiles and is *correct* though – 463035818_is_not_an_ai Jan 13 '23 at 22:32