0

Here I have a simplified version of a linked-list implementation I have been working on. I would like to keep a count of component elements (nodes) as a private member, and then let the Component constructor and destructor completely handle the variable count.

However, I'm getting a compiler error (VS2015) disallowing access to count by any member functions (including the constructor and destructor) that I have in Component:

'count': undeclared identifier

Why does the friend declaration not grant that access in this case?

class Outer {
private:
    class Component;
    friend class Component;
public:
    Outer() : count(0) {}
    unsigned int size() {
        return count;
    }
    void methodThatCreatesComponents() {
        entryPoint = new Component(nullptr);
        // I don't want to have to write ++count; every time I construct
    }
    void methodThatDeletesComponents() {
        delete entryPoint;
        // I don't want to have to write --count; every time I delete
        entryPoint = nullptr;
    }
private:
    unsigned int count;
    Component* entryPoint;
    class Component {
    public:
        Component(Component* next) {
            ++count;
        }
        ~Component() {
            --count;
        }
    private:
        Component* next;
    };
};
Aposhian
  • 801
  • 1
  • 10
  • 27
  • C++ doesn't automatically allow inner classes to have access to the outer classes. See [this link](http://en.cppreference.com/w/cpp/language/nested_types). – callyalater Feb 22 '16 at 21:53
  • 1
    Second, `class Component() {...};` should be `class Component {...}` (no parentheses). – callyalater Feb 22 '16 at 21:55
  • @callyalater Which is why I thought using friend would work, but thanks for the link, that helps. – Aposhian Feb 22 '16 at 22:07
  • @callyalater The parentheses were a typo when I wrote up the question. It's fixed now. – Aposhian Feb 22 '16 at 22:08

3 Answers3

0

You need to qualify count with proper scope.

I am guessing that count is expected to be a static member of Outer. Then, you an use:

Component(Component* next) {
   ++Outer::count;
}
~Component() {
   --Outer::count;
}

If count is supposed to be a non-static member of Outer, Component needs an instance of Object to be able to access the count member variable.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
0

You have to access private members of outer class via a pointer to the outer class. The compiler errors are not about level of access, they are probably stating something like "count was not declared in the scope".

The following should solve the problem:

class Component {
public:
    Component(Outer* outer, Component* next) : outer(outer) {
        ++outer->count;
    }
    ~Component() {
        --outer->count;
    }
private:
    Outer* outer;
    Component* next;
};

P.S. There is also a hacky way to get a pointer to an outer class via offsetof:

class Component {
public:
    Component(Component* next) : outer(outer) {
        ++outer()->count;
    }
    ~Component() {
        --outer()->count;
    }
private:
    Outer* outer() {
        return (void*)this - offsetof(Outer, entryPoint);
    }

    Outer* outer;
    Component* next;
};
Oleg Andriyanov
  • 5,069
  • 1
  • 22
  • 36
  • This would work, but is rather ugly. Do I really need to pass `this` as a parameter every time I call the Constructor? Plus, this adds an extra pointer of memory space to every instance of Component... I would almost rather just pair mutator statements with my constructors/deletes. – Aposhian Feb 22 '16 at 22:01
  • 1
    @Aposhian Now your question is rather about the design than C++ language. If you want to modify `count` every time the node is inserted/deleted, I'd prefer having functions `insert()` and `remove()` in the `class Outer` which would do `count++` and `count--`. If `Component` represents a node of a linked list, then IMO it should not know anything about its container, including its size. – Oleg Andriyanov Feb 22 '16 at 22:10
  • 1
    @Aposhian it shouldn't be the job of `Outer::Component` to adjust a member variable of `Outer` in the first place IMO. Like Oleg remarked, put insert and remove functions in the `Outer` class. Presumably the user is not going to see the `Component` class anyhow, so why bother with this friend contraption. Make `Component` a simple struct and do the logic in `Outer`. – rwols Feb 22 '16 at 22:56
0

Alright I think that I came up with a suitable method that works around the fact that Component can't know about about the instance of Outer that it is inside without storing a this for each instance. Using helper functions:

class Outer {
private:
    class Component;
public:
    Outer() : count(0) {}

    unsigned int size() {
        return count;
    }
    void methodThatCreatesComponents() {
        // other functionality
        entryPoint = createComponent(nullptr);
    }
    void methodThatDeletesComponents() {
        // other functionality
        deleteComponent(entryPoint);
    }
private:
    unsigned int count;
    Component* entryPoint;
    class Component {
    public:
        Component(Component* next) : next(next) {}
        ~Component() {}
    private:
        Component* next;
    };
    Component* createComponent(Component* next) {
        ++count;
        return new Component(next);
    }
    void deleteComponent(Component*& toDelete) {
        --count;
        delete toDelete;
        toDelete = nullptr;
    }
};

This way I don't have to worry about modifying the count every time I construct or destroy, or a deluge of this or other structures intended to compromise the nested object structure. The other answers definitely helped me see what was wrong with my perception of inner classes. Ciao!

Aposhian
  • 801
  • 1
  • 10
  • 27