Thread: Accessing protected class members

  1. #1
    Confused
    Join Date
    Nov 2002
    Location
    Warwick, UK
    Posts
    209

    Accessing protected class members

    Hello,

    I have a base class Paths, and a derived class LanguagePaths, which inherits Paths. There are various members of Paths, namely two doubles and a std::list <int>, which I'd like to copy from a Paths object into a LanguagePaths object.

    In order to do so, I've overloaded the operator= in LanguagePaths, as follows :

    Code:
    // LANGUAGE PATHS CLASS
    #ifndef _LANGUAGEPATHS_H
    #define _LANGUAGEPATHS_H
    
    //#include <list>
    #include <set>
    #include "paths.h"
    #include "shortcuts.h"
    
    class LanguagePaths : public Paths	// INHERITS PATHS
    {
    	public:
    		
    		// Constructor
    		LanguagePaths();
    				
    		// Accessors
    		bool banned(uint);		// Check if a production is banned
    		void insert(uint);		// Insert a ban
    		listitr marker();			// Marker position
    		listitr setmarker(listitr);	// Set the position of the marker
    				
    		// Overloaded operator
    		LanguagePaths operator= (const Paths &);
    		
    						
    	private:
    		
    		// Ban list
    		set <uint> ban;
    		
    		// Marker position
    		listitr markerpos;
    };
    
    #endif
    Code:
    // SNIPPET OF LANGUAGEPATHS.CPP
    // Overloading the equals operator
    LanguagePaths LanguagePaths::operator=(const Paths & original)
    {
    	// Set length and coefficients equal
    	length = original.length;
    	coefficient = original.coefficient;
    	
    	// Set path description to be the same
    	path = original.path;
    }
    Code:
    // PATHS CLASS
    #ifndef _PATHS_H
    #define _PATHS_H
    
    #include <list>
    #include "edge.h"
    #include "vertex.h"
    #include "graph.h"
    #include "shortcuts.h"
    using namespace std;
    
    
    
    
    class Paths
    {
    	public:
    		
    		// Constructor
    		Paths();
    		
    		// Accessors
    		uint back();			// Returns the ID of the vertex at the end of the path
    		uint front();			// Returns the ID of the vertex at the front of the path
    		int size();			// Returns the size of the path, in number of nodes
    		double getLength(Graph &);	// Returns the length of the path in spatial units
    		double getCoefficient(Graph &);	// Returns the trip coefficient of the path
    			
    		// Iterators
    		listitr begin();	// Returns an iterator to the beginning of the list
    		listitr end();		// Returns an iterator to the end of the list
    				
    		// Other methods
    		void push_back(uint);		// Add a vertex to the end of the path
    		bool contains(uint);		// Check if the path contains a certain vertex
    		void clear();			// Clear the path list completely
    		void incLength(double);		// Increase the length of the path
    		void incCoefficient(double);	// Increase the trip coefficient
    
    				
    	protected:
    		
    		double length;		// Path length
    		double coefficient;	// Path coefficient
    		list <uint> path;	// Path description
    };
    
    
    #endif


    I'm struggling to use my equals operator. I have a list <Paths> which contains path objects, and want to create a std::priority_queue <LanguagePaths>, like so :

    Code:
        // Create a priority queue using specified comparison function
        priority_queue < LanguagePaths, vector <LanguagePaths>, PathCompare > pq(comparefunction);
        
        // Create a temp LanguagePaths object
        LanguagePaths temp;
        
        for(list<Paths>::iterator i = finallist.begin(); i != finallist.end(); i++)
        {
        	temp = *i;
        	pq.push(temp);
        }

    I get these errors :
    Code:
    paths.h: In member function 'LanguagePaths LanguagePaths::operator=(const Paths&)':
    paths.h:45: error: 'double Paths::length' is protected
    I get the same error for Paths::coefficient and Paths::path.

    I was under the impression that protected members of a base class could be accessed by a derived class. I'm not quite sure what I should be doing.

    Any help would be greatly appreciated. Thanks very much !
    Quentin
    Last edited by Korhedron; 07-29-2010 at 06:20 AM.

  2. #2
    The larch
    Join Date
    May 2006
    Posts
    3,573
    A LanguagePaths object can only access the protected members of other LanguagePaths objects, not any protected members of other classes with the same base class.

    Because it takes a Paths object as an argument, LanguagePaths has no business messing around with it, or else it might be manipulating a completely unrelated object to itself.

    You should try to use the public interface of Paths.

    If I'm not mistaken, using protected members is a bit of an antipattern anyway: the base class can't enforce its invariants, because derived classes can manipulate it directly.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  3. #3
    Confused
    Join Date
    Nov 2002
    Location
    Warwick, UK
    Posts
    209
    Hi anon,

    Given LanguagePaths inherits Paths, surely it can access Paths' protected members ? That's the difference between private and protected. Am I wrong ?

    Thanks,
    Quentin

  4. #4
    The larch
    Join Date
    May 2006
    Posts
    3,573
    No, it can access the protected parts of other LanguagePath objects. If it could access protected members of any Paths objects, it would mean a LanguagePath could mess around with a SymbolPath or whatever other classes you derive from Paths.

    Code:
    class Base
    {
        protected: int x;
    };
    
    class Child
    {
         void ok(Child& child) { x = 20; child.x = 10; }
         void not_ok(Base& base) { base.x = 10; }
    };
    Last edited by anon; 07-29-2010 at 06:52 AM.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  5. #5
    Confused
    Join Date
    Nov 2002
    Location
    Warwick, UK
    Posts
    209
    It should be able to access protected members of classes that it is derived from, not members on its same hierarchical level. So, it should have access to protected Paths objects, but not protected SymbolPaths objects. LanguagePaths objects can access private members of other LanguagePaths objects - that's what you're describing.

  6. #6
    The larch
    Join Date
    May 2006
    Posts
    3,573
    The point is that in

    Code:
    LanguagePaths LanguagePaths::operator=(const Paths & original)
    you don't know what Paths is. It could be a reference to another LanguagePaths object, it could be a reference to another class derived from Paths to which LanguagePaths has no relation (except for common base class). Therefore the protected members of the original are unaccessible to the current LanguagePaths object.

    Example:
    Code:
    #include <algorithm>
    
    class Value
    {
        protected:
            int x;
        public:
            int get_value() const { return x; }
    };
    
    class SingleDigitValue: public Value
    {
        public:
            void set_value(int n)
            {
                x = std::max(std::min(9, n), 0);  //invariant, value always in certain range [0...9]
            }
    };
    
    class AnyValue: public Value
    {
        public:
            void set_value(int n) { x = n; }
            void set_value_of(Value& v, int n)
            {
                v.x = n;  //your error
            }
    };
    
    int main()
    {
        SingleDigitValue single;
        single.set_value(5);
        AnyValue any;
        any.set_value_of(single, 100);
        //it it worked single.x would now be 100, despite the restriction that it should be in range [0..9]
    }
    Last edited by anon; 07-29-2010 at 07:28 AM.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  7. #7
    Confused
    Join Date
    Nov 2002
    Location
    Warwick, UK
    Posts
    209
    I understand my error now - I wasn't differentiating between objects and their instances. Thanks very much for the help !

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 7
    Last Post: 08-04-2009, 11:40 AM
  2. Linking errors with static var
    By Elysia in forum C++ Programming
    Replies: 8
    Last Post: 10-27-2007, 05:24 PM
  3. Screwy Linker Error - VC2005
    By Tonto in forum C++ Programming
    Replies: 5
    Last Post: 06-19-2007, 02:39 PM
  4. accessing class variables
    By pug in forum C# Programming
    Replies: 3
    Last Post: 05-20-2005, 08:46 AM
  5. structure vs class
    By sana in forum C++ Programming
    Replies: 13
    Last Post: 12-02-2002, 07:18 AM