views:

396

answers:

3

I get the following error in Visual Studio 2008: error C2248: 'Town::Town' : cannot access private member declared in class 'Town'. It looks like the constructor is unable to access the members of its own class. Any idea what's going on? Here's the code:

I have this:

template<class T> class Tree{...}

And this class:

class Town{
    Town(int number):number(number){};
    ...
private: 
    int number;
};

Which is used in this class:

class Country{
public:
    StatusType AddTown(Shore side, int location, int maxNeighborhoods);
private:
    Tree<Town> towns[2];
    ...
}

And here's the AddTown function:

StatusType Country::AddTown(Shore side, int location, int maxNeighborhoods){
    if (maxNeighborhoods<0 || location<0){
     return INVALID_INPUT;
    }
    Town* dummy= new Town(location);//Here be error C2248
    if (towns[side].find(*dummy)!=NULL){
     delete dummy;
     return FAILURE;
    }
    SouthBorder* dummyBorder;
    (side==NORTH)?dummyBorder=new SouthBorder(location,0):dummyBorder=new SouthBorder(0,location);
    if (southBorders.find(*dummyBorder)!=NULL){
     delete dummyBorder;
     return FAILURE;
    }
    towns[side].add(*dummy);
    delete dummyBorder;
    return SUCCESS;
}
A: 

You declared a local variable for the function that hides the member variable:

Town(int number):number(number){};

Try this instead

Town(int num):number(num){};

Hans
The initialization list is a little special to this effect. A parameter by the same name will not hide an attribute while in the initialization list. The parameter will hide the name of the attribute wherever possible. When the compiler encounters ': number(number)' the first 'number' must be an attribute for the code to compile. The second 'number' can be either and the parameter hides the attribute there (as everywhere inside the constructor block). But the OP code is correct.
David Rodríguez - dribeas
+10  A: 

By default class access level is private. If you do not add a public: before the Town constructor it will be private.

class Town{
public: // <- add this
    Town(int number):number(number){};
    ...
private: 
    int number;
};
David Rodríguez - dribeas
Thank you. That was a stupid mistake...
Epsilon Vector
+3  A: 

This code had both the logic problems listed above. Both the non public declaration and the hiding of the member variables by using the same name passed as internal.

Considering we are talking about the 'number' variable as an example.

In the past such as in c++ member variables that were private internal variables would be prefixed with 'm_number'. Or some would do just '_number'.

Just 'num' is a good rename but it may not be clear that it is just the same value. I suppose this is a problem of internal private member variable naming that hasn't really been solved.

Python uses 'self.number' which would distinguish from 'number' passed in which is a decent solution.

But whatever the platform, it is always good to have a private variable member naming system that helps you to avoid hacks at the points that you have name collisions.

Ryan Christensen
+1 on the general idea. But, while common, you should not prefix with an underscore '_', as the standard reserves those names to the 'implementation', where implementation is the compiler/STL implementor. You can also use 'this' in C++ as you would do 'self' in python to discriminate the attribute from other identifiers (local variables/parameters).
David Rodríguez - dribeas