2

I am trying to figure out how to make a private/protected member of an inner type accessible to its enclosing class.

My search led me to many questions about how to access an enclosing member from the inner class (e.g.) but this is not what I need. Many other posts traverse Java, and this is definitely not what I need. This is C++.

Consider this MCVE:

#include <iostream>

struct bla
{
    bla( );
    ~bla( );

    class inner;

    inner *_inner;
};

class bla::inner
{
public:
    inner( )
    :   field( 13 )
    {}

private:
    friend struct bla;

    unsigned field;
};


bla::bla( )
:   _inner( new inner )
{}

bla::~bla( )
{
    delete _inner;
}

int main( )
{
    bla _bla;
    _bla._inner->field = 42;
    std::cout << "bla::_inner->field: " << _bla._inner->field << std::endl;
}

Live example

The only question I could find out treating what I need is C++ Outer class access Inner class's private - why forbidden, but the proposed solution does not work for me:

$ g++ -std=c++14 -Wall inner_class.cpp -o inner_class
inner_class.cpp: In function ‘int main()’:
inner_class.cpp:23:11: error: ‘unsigned int bla::inner::field’ is private
  unsigned field;
           ^
inner_class.cpp:39:15: error: within this context
  _bla._inner->field = 42;
               ^
inner_class.cpp:23:11: error: ‘unsigned int bla::inner::field’ is private
  unsigned field;
           ^
inner_class.cpp:40:54: error: within this context
  std::cout << "bla::_inner->field: " << _bla._inner->field << std::endl;

How to properly give bla access to field? Did I miss any silly detail?

Thanks in advance.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
j4x
  • 3,595
  • 3
  • 33
  • 64
  • 3
    You can't. Not in the context of `main` anyway. `main` has no access to private or protected fields, there's no way around that. – Hatted Rooster Jun 13 '18 at 12:56
  • 1
    "but the proposed solution does not work for me:" This would be the line that suggests this is an XY problem. I would suggest you rewind a thought processes or two and say what the issue is that you're trying to solve. – UKMonkey Jun 13 '18 at 12:58
  • @SombreroChicken I think you nailed it. I have just revised my code and found out that I must provide accessors to my "field" in "bla". Please post an answer so I can accept it. – j4x Jun 13 '18 at 13:00
  • @SombreroChicken " main has no access to private or protected fields, there's no way around that" - yes there is: `friend int main();` (Im not saying you *should* do it, just that you *could*) – virgesmith Jun 13 '18 at 13:46

3 Answers3

4

Your code is correctly granting the friendship required for bla to access the private members of bla::inner. However, your problem is that you're not accessing the private member in bla (which would have access), you're accessing it in main, which of course has no access.

If you want bla to be able to access bla::inner::field, you need to give bla some functions for accessing it. Example:

struct bla
{
    bla( );
    ~bla( );

    class inner;

    inner *_inner;

    void setInnerField(int val) { _inner->field = val; }
};

// The rest as before

int main( )
{
    bla _bla;
    _bla.setInnerField(42);
    std::cout << "bla::_inner->field: " << _bla._inner->field << std::endl;
}

If, on the other hand, you want to give all outside code (such as main) access to the field, just make it public.

Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
  • Thank you very much @Angew. Of course I also need an accessor to read `field` back. I apologise but Sombrero Chicken's response came first, so I think it is fair to consider his response. Thank you again. – j4x Jun 13 '18 at 13:07
2

Making main as friend of bla::inner should work.

    class bla::inner
{
public:
    inner( )
    :   field( 13 )
    {}

private:
    friend struct bla;
    friend int main(); // Make main friend of bla
    unsigned field;
};
SaurabhS
  • 633
  • 1
  • 7
  • 18
  • Well, technically I believe it indeed works but is not that beautiful. Other responses make it cleaner. Thanks. – j4x Jun 13 '18 at 13:26
1

You can't.

You seem to think that because _bla is an object of bla and bla is the outer class that you can access private fields of inner outside of bla. This is not the case.

Access modifiers work on scope, not on the objects you're operating on. You can access the private fields of inner in the class body of bla (in its methods etc). Not outside of it.

Hatted Rooster
  • 35,759
  • 6
  • 62
  • 122