1

I'm attempting to read the int data variable in parent class Foo in child class Bar.

The variable data is initialized under a private: and uses friend class Bar<T>.

I am receiving the following compiler error:

$ g++ scopetest.cpp
scopetest.cpp: In constructor ‘Bar<T>::Bar()’:
scopetest.cpp:33:12: error: ‘data’ was not declared in this scope
    cout << data;
            ^

I thought friend class Bar<T> would make everything under private: visible to Bar<T>. But this doesn't seem to be the case.

Here is my code:

using namespace std;

template <typename T>
class Bar; 

template <typename T> 
class Foo{
    private:
        friend class Bar<T>;
        int data;

    public:
        Foo() {
            data = 0;
        }

        ~Foo() {

        } 

};

template <class T>
class Bar : public Foo<T> { 
    public: 
        Bar<T>() : Foo<T>() {  
            cout << data;   
        }

        ~Bar() { }

};

int main(int argc, char* argv[]){   

}

Is there anything obvious that I am doing wrong here?

Shoe
  • 74,840
  • 36
  • 166
  • 272
Bob Shannon
  • 638
  • 2
  • 10
  • 19
  • @dvnrrs I've done this, and it still throws an out of scope error. Removed the friend declaration and changed it to protected. Hrm. – Bob Shannon Mar 05 '14 at 01:52
  • @dvnrrs After reading the other answer, it works now that I put `this->data`. – Bob Shannon Mar 05 '14 at 01:55
  • You shouldn't need to do that if it's `protected`. (It won't hurt, but it may be a sign something wasn't done quite right.) If you post your attempt I'll see if I can spot the problem. – TypeIA Mar 05 '14 at 01:57
  • I see. I was afraid of that. Posting now. – Bob Shannon Mar 05 '14 at 01:58
  • It's up there now. It throws the exact same out of scope error. – Bob Shannon Mar 05 '14 at 02:00
  • Also unsure why this isn't working, but it might be worth noting that since you don't need the friending anymore you no longer have to forward declare class Bar above Foo. I also don't think you need to use the template in Bar's default ctor, might be able to just say `Bar() : Foo()` – Instinct Mar 05 '14 at 02:06
  • 1
    I looked into this further this morning and discovered that it's a peculiar (to me) [behavior of templates](http://stackoverflow.com/questions/15813863/member-of-base-class-template-is-out-of-scope-in-derived-class-template-with-sam). If you try this with non-template classes, it works fine (you can access the `protected` member without `this->`). But because of the way templates work, the compiler requires you to use `this->` (see the link for a discussion). I did not know this. So, awesomeyi's answer below is correct: use `protected` and access it with `this->`. – TypeIA Mar 05 '14 at 14:36
  • Using this-> to access the parent class field seems a bit weird, but it works. I wonder why the language was designed like this for templates. – Bob Shannon Mar 05 '14 at 19:34

1 Answers1

2

Replace data with this->data, live demo: http://ideone.com/UNR0IM. Note that this is the far from optimal solution. The protected access specifier was made just for this purpose.

class Foo
{
    protected:
        int data;
 ....
}
yizzlez
  • 8,757
  • 4
  • 29
  • 44
  • This solution works, but I am definitely interested in doing it the suggested proper way. However, using protected and removing the friend statement like @dvnrrs suggested still yields an out of scope error? – Bob Shannon Mar 05 '14 at 01:54
  • @Bob you can do `Bar::data` or `this->data` with the proper method – yizzlez Mar 05 '14 at 02:12