Thread: Why am I getting this error?

  1. #1
    Registered User
    Join Date
    Mar 2007
    Posts
    32

    Why am I getting this error?

    I have a Graph.h file....

    Code:
    #ifndef GRAPH_H_
    #define GRAPH_H_
    
    #include <iostream>
    #include <string>
    #include <sstream>
    #include <fstream>
    #include <list>
    #include <map>
    #include "GraphStuff.h"
    
    struct Vertex;
    
    class Graph
    {
      public:
        Graph( ) { }
        ~Graph( );
        void addEdge( const std::string & sourceName, const std::string & destName, double cost );
        void printPath( const std::string & destName ) const;
        void unweighted( const std::string & startName );
        void dijkstra( const std::string & startName );
        void addVertex (const string & startName);
              
      private:
        Vertex * getVertex( const std::string & vertexName );
        void printPath( const Vertex & dest ) const;
        void clearAll( );
    
        typedef map<std::string,Vertex *,less<std::string> > vmap;
    
          // Copy semantics are disabled; these make no sense.
        Graph( const Graph & rhs ) { }
        const Graph & operator= ( const Graph & rhs )
          { return *this; }
    
        vmap vertexMap;
    };
    
    #endif /*GRAPH_H_*/
    and a Movie.h file....
    Code:
    #ifndef MOVIE_H_
    #define MOVIE_H_
    
    #include <string>
    #include <vector>
    
    #include "ActorDB.h"
    #include "Graph.h"
    #include "GraphStuff.h"
    
    class Actor;
    
    
    /**
     * A class that represents a Movie.  These objects contain the movie 
     * title, the year the movie was released, and a cast list.
     */
    class Movie
    {
    public:
    	
    	Movie();
    	
    	/** 
    	 * Build a new movie.  
    	 * 
    	 * @param t The title of the movie
    	 * @param y The year string for this movie
    	 * @param a A pointer to the ActorDB object.  The movie stores actor tags 
    	 * taken from this object.
    	 * 
    	 */ 
    	Movie(const std::string& t, const std::string& y, ActorDB* a = 0);
    	
    	/// return the title of the movie
    	std::string title() const;
    	
    	/// returns the year in which the movie was made.
    	std::string year() const;
    
    	/**
    	 * Add an actor to the movie's cast list.  Takes a tag from the actor database
    	 * as input.  Note that it's marked "const" -- the cast list does not participate
    	 * in the ordering of Movies;  two Movies are logically equal if their titles and years
    	 * are equal.  Thus, the cast list is a mutable member of the Movie.
    	 * 
    	 * @param a a tag referring to an actor to add to the list.  To dereference such a tag, 
    	 * we have to pass it back to the ActorDB object it came from.
    	 */	
    	void add_actor(ActorDB::tag a) const;
    	
    	/** 
    	 * Returns a vector of Actors, the cast of this movie.
    	 * 
    	 * @return a vector of copies of the Actors with roles in this movie.
    	 */
    	std::vector<Actor> cast() const;
    	
    	void actorConnections(ActorDB::tag a) const;
    	
    	void printPath(const string & name1, const string & name2);
    	
    	
    private:
    	/// A pointer to the ActorDB that stores the actors with roles in this movie.
    	/// Used to resolve the ActorDB::tag objects that we store.
    	ActorDB* adb;
    	
    	/// The title of this movie.
    	std::string the_title;
    	
    	/// The year in which this movie was released.
    	std::string the_year;
    	
    	/// A vector of ActorDB::tag objects, referring to the Actor objects
    	/// stored in *adb that represent our cast.
    	mutable std::vector<ActorDB::tag> the_cast;
    	
    	///The private graph for the Kevin Bacon Problem
    	mutable Graph actorGraph;
    };
    
    #endif /*MOVIE_H_*/
    However, I am getting an error in the Graph.h file. It says "error: Graph::Graph(const Graph&) is private"

    Does anybody know why I'm getting this error?

  2. #2
    For Narnia! Sentral's Avatar
    Join Date
    May 2005
    Location
    Narnia
    Posts
    719
    Are you trying to access a private member outside the original class?
    Videogame Memories!
    A site dedicated to keeping videogame memories alive!

    http://www.videogamememories.com/
    Share your experiences with us now!

    "We will game forever!"

  3. #3
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    >> // Copy semantics are disabled; these make no sense.
    That comment is in the Graph code. It means that copying this object doesn't make sense, so you cannot do it. Somewhere else in your code you are trying to copy a Graph object, and the compiler is complaining because the Graph class is not supposed to be copied.

    Since your Movie class has a Graph member variable, that also means that you cannot copy a Movie object (because it will try to copy the Graph member). So it is posible that the compiler is complaining becuase you are trying to copy a Movie object.

    There might be an error above or below the error message that you posted that says where the copy is occurring. If you cannot find it, make sure you don't return a Movie or Graph by value from a function, and make sure you don't have any vector<Movie>'s or vector<Graph>'s anywhere (or any other STL container of those).

  4. #4
    Registered User
    Join Date
    Mar 2007
    Posts
    32
    This is the error message:

    Code:
    make -k all 
    Building file: ../Graph.cpp
    Invoking: GCC C++ Compiler
    g++ -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"Graph.d" -MT"Graph.d" -o"Graph.o" "../Graph.cpp"
    ../Graph.cpp: In member function `void Graph::printPath(const Vertex&) const':
    ../Graph.cpp:72: error: expected primary-expression before '<<' token
    ../Graph.cpp: In member function `void Graph::unweighted(const std::string&)':
    ../Graph.cpp:109: warning: comparison between signed and unsigned integer expressions
    ../Graph.cpp: In member function `void Graph::dijkstra(const std::string&)':
    ../Graph.cpp:139: warning: comparison between signed and unsigned integer expressions
    ../Graph.cpp:151: warning: comparison between signed and unsigned integer expressions
    ../Graph.cpp:168:2: warning: no newline at end of file
    make: *** [Graph.o] Error 1
    Building file: ../MovieDB.cpp
    Invoking: GCC C++ Compiler
    g++ -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"MovieDB.d" -MT"MovieDB.d" -o"MovieDB.o" "../MovieDB.cpp"
    ../Graph.h: In copy constructor `Movie::Movie(const Movie&)':
    C:/MinGW/bin/../lib/gcc/mingw32/3.4.2/../../../../include/c++/3.4.2/bits/stl_construct.h:81:   instantiated from `void std::_Construct(_T1*, const _T2&) [with _T1 = Movie, _T2 = Movie]'
    C:/MinGW/bin/../lib/gcc/mingw32/3.4.2/../../../../include/c++/3.4.2/bits/stl_tree.h:365:   instantiated from `std::_Rb_tree_node<_Val>* std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_create_node(const _Val&) [with _Key = Movie, _Val = Movie, _KeyOfValue = std::_Identity<Movie>, _Compare = MovieComp, _Alloc = std::allocator<Movie>]'
    C:/MinGW/bin/../lib/gcc/mingw32/3.4.2/../../../../include/c++/3.4.2/bits/stl_tree.h:781:   instantiated from `typename std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert(std::_Rb_tree_node_base*, std::_Rb_tree_node_base*, const _Val&) [with _Key = Movie, _Val = Movie, _KeyOfValue = std::_Identity<Movie>, _Compare = MovieComp, _Alloc = std::allocator<Movie>]'
    C:/MinGW/bin/../lib/gcc/mingw32/3.4.2/../../../../include/c++/3.4.2/bits/stl_tree.h:875:   instantiated from `std::pair<typename std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator, bool> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::insert_unique(const _Val&) [with _Key = Movie, _Val = Movie, _KeyOfValue = std::_Identity<Movie>, _Compare = MovieComp, _Alloc = std::allocator<Movie>]'
    C:/MinGW/bin/../lib/gcc/mingw32/3.4.2/../../../../include/c++/3.4.2/bits/stl_set.h:314:   instantiated from `std::pair<typename std::_Rb_tree<_Key, _Key, std::_Identity<_Key>, _Compare, _Alloc>::const_iterator, bool> std::set<_Key, _Compare, _Alloc>::insert(const _Key&) [with _Key = Movie, _Compare = MovieComp, _Alloc = std::allocator<Movie>]'
    ../MovieDB.cpp:17:   instantiated from here
    ../Graph.h:33: error: `Graph::Graph(const Graph&)' is private
    C:/MinGW/bin/../lib/gcc/mingw32/3.4.2/../../../../include/c++/3.4.2/bits/stl_construct.h:81: error: within this context
    make: *** [MovieDB.o] Error 1
    make: Target `all' not remade because of errors.
    Build complete for project Project 3

  5. #5
    Registered User
    Join Date
    Apr 2007
    Location
    Sweden
    Posts
    41
    The problem is in Movie's copy constructor, isn't it? Since you haven't implemented one, the default one is used in MovieDB.cpp at line 17... and it tries to copy the actorGraph field.

  6. #6
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    So it looks like you have a map or some other STL container holding Movies. You cannot do that as long as Graph is not copyable. Find the container that holds Movies and post it and what you use it for so we can give options. Possible fixes include changing Movie's or Graph's copying to make it possible, or holding pointers in the container instead of objects, or using a different kind of container that doesn't require copying.

  7. #7
    Registered User
    Join Date
    Mar 2007
    Posts
    32
    MovieDB.h....

    Code:
    #ifndef MOVIEDB_H_
    #define MOVIEDB_H_
    
    #include <set>
    #include <string>
    
    class Movie;
    
    /**
     *  A comparison operator for Movies, so we can build a set of them
     */
    struct MovieComp
    {
    	bool operator()(const Movie& lhs, const Movie& rhs) const;
    };
    
    /**
     * An exception object.  Throw one of these if a movie is not found during a search.
     */
    struct MovieNotFound 
    {
    	MovieNotFound(const std::string& t, const std::string y)
    		: title(t), year(y)
    	{}
    
    	std::string what() {
    		return "Movie not found: " + title + " from year " + year;
    	}
    	
    	std::string title;
    	std::string year;
    };
    
    /**
     * Objects of this type store a collection of Movies.  We support fast searching.
     */
    class MovieDB
    {
    
    public:
    	/// clients should use the tag type to store references to the movies that 
    	/// we store here.
    	typedef std::set<Movie, MovieComp>::const_iterator tag;
    
    	/// Constructs an empty database.
    	MovieDB();
    	
    	/// Destructor currently does nothing not done automatically.
    	~MovieDB();
    	
    	/**
    	 * add a movie to the database.  Takes O(log(n)) time.
    	 * 
    	 * @param m The movie to add.  A copy will be placed in the database.
    	 * @return a tag by which the movie can be referenced.  Pass this to 
    	 * get_movie() to retrieve a reference to the stored movie.  
    	 */
    	tag add_movie(const Movie& m);
    	
    	/** 
    	 * Retrieve a reference to the stored movie referred to by the tag.  Runs in 
    	 * constant time.
    	 * 
    	 * @param t a tag referring to one of our movies
    	 * @return a constant reference to the movie corresponding to t
    	 */
    	const Movie& get_movie(tag t) const;
    	
    	/** 
    	 * This version of get_movie searches for a movie with exactly matching title and year.
    	 * Runs in O(log(n)) time.
    	 * 
    	 * @param title The title of the movie to search for.
    	 * @param year The release year of the movie to search for.
    	 * @return A constant reference to the matching movie in the database.
    	 * @throw A MovieNotFound exception is thrown if no matching movie is found.
    	 */ 
    	const Movie& get_movie(const std::string& title, const std::string& year) const;
    	
    private:
    	/// We store our data in a std::set.
    	std::set<Movie, MovieComp> data;
    };
    
    #endif /*MOVIEDB_H_*/
    MovieDB.cpp.....

    Code:
    #include "MovieDB.h"
    #include "Movie.h"
    
    #include <string>
    using namespace std;
    
    MovieDB::MovieDB()
    {
    }
    
    MovieDB::~MovieDB()
    {
    }
    
    MovieDB::tag MovieDB::add_movie(const Movie& m) 
    {
    	pair<tag, bool> p = data.insert(m);
    	
    	return p.first;
    }
    	
    const Movie& MovieDB::get_movie(MovieDB::tag t) const {
    	return *t;
    }
    
    const Movie& MovieDB::get_movie(const std::string& title, const std::string& year) const
    {
    	Movie m(title, year);
    	tag t = data.find(m);
    	if (t == data.end())
    		throw MovieNotFound(title, year);
    	
    	return *t;
    }
    
    bool MovieComp::operator()(const Movie& lhs, const Movie& rhs) const
    {
    	if (lhs.title() < rhs.title())
    		return true;
    	else if (lhs.title() == rhs.title() && lhs.year() < rhs.year())
    		return true;
    	return false;
    }

  8. #8
    Registered User
    Join Date
    Apr 2007
    Location
    Sweden
    Posts
    41
    Code:
    MovieDB::tag MovieDB::add_movie(const Movie& m) 
    {
    	pair<tag, bool> p = data.insert(m);
    Yup... data is a std::set, and with data.insert(m) (I suppose) it tries to copy m into its own internals, which (I suppose) it would do with Movie's copy constructor. Here it is the default one, which tries to copy every field in Movie - including actorGraph, which cannot be copied!

  9. #9
    Registered User
    Join Date
    Mar 2007
    Posts
    32
    Is there any way to fix this?

  10. #10
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    Possible fixes include changing Movie's or Graph's copying to make it possible, or holding pointers in the container instead of objects, or using a different kind of container that doesn't require copying.

    You could change the Graph member of Movie to be a shared_ptr<Graph>. This means that any copies of the same movie will share the same graph.

    You could use ptr_set from Boost instead of a regular set. I haven't used it myself, but the point of it is to allow you to hold pointers in the set so that no copying is done.

    Both shared_ptr and ptr_set come from Boost. If you can't or don't want to use Boost, then you could also use raw pointers in either case, although those take more effort to get right. Based on what I see, I would think the first option is better, changing the Graph member of Movie to be a pointer. It makes sense to me that if you copy a Movie that the copies would share the Graph while they are alive.

  11. #11
    Registered User
    Join Date
    Mar 2007
    Posts
    32
    I would think the first option is better, changing the Graph member of Movie to be a pointer.
    I'm not too familiar with pointers, but would I change

    Code:
    ///The private graph for the Kevin Bacon Problem
    	mutable Graph actorGraph;
    to

    Code:
    mutable Graph *actorGraph;
    If I do that, which I'm sure is wrong, then the error in the Graph.h file went away but I now have errors in my Movie.cpp class in the function actorConnections and printPath.
    Last edited by tallguy; 04-02-2007 at 02:00 PM.

  12. #12
    Registered User
    Join Date
    Mar 2007
    Posts
    32
    This is actorConnections function in my Movie.cpp file:

    Code:
    void Movie::actorConnections(ActorDB::tag a) const
    {
    	for (unsigned i = 0; i <the_cast.size(); ++i)
    	{
    		actorGraph.addEdge(adb->get_actor(a).name(), adb->get_actor(the_cast[i]).name(), 1);
    		actorGraph.addEdge(adb->get_actor(the_cast[i]).name(), adb->get_actor(a).name(), 1);
    	}
    }
    
    void Movie::printPath(const string & name1, const string & name2)
    {
    	actorGraph.unweighted(name1);
    	actorGraph.printPath(name2);
    }

  13. #13
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    >> mutable Graph *actorGraph;
    This is how you would change it to a pointer, but after thinking about it I realized that just changing to a plain pointer will create the same problem as you had before (you have to copy the graph but you cannot).

    I think the better solution is to use boost::shared_ptr. Is that available to you? It is actually easier to use than a raw pointer, you just have to allocate space in the constructor.

    If Boost is not available to you, then leave the Graph as a regular, non-pointer member and use a set of pointers in MovieDB:
    Code:
    std::set<Movie*, MovieComp> data;
    This takes a lot more work than the shared_ptr solution, but if you can't use Boost or any other shared_ptr implementation it is the best I can think of. In addition to changing that set definition, you need to change MovieComp to compare pointers instead of regular objects (or making another version that works on pointers). You need to use new to allocate space for all Movies that go into that set, and use delete on all Movies that you erase from the set. You also need to delete all Movies in the set when you clear it or when the MoviesDB object is destructed.

    There might also be other solutions I haven't presented, but I can't think of any at the moment. Hopefully others will chime in if they have thoughts.

    One last question, you want an actorGraph for each Movie, right? You don't want one actorGraph shared between all Movies, right?

  14. #14
    Registered User
    Join Date
    Mar 2007
    Posts
    32
    I need one actorGraph for all the movies because this is the Kevin Bacon problem, so I need connections(vertices) between all actors in all movies. I know, this will be a lot of edges.

    Yes I do have Boost available to me.

    I changed mutable Graph actorGraph to

    shared_ptr<Graph> actorGraph;

    but that was an error. What's wrong with that declaration?

    ok i changed it to boost::shared_ptr<Graph> actorGraph; and that worked but now I still have errors in my actorConnections and printPath functions.
    Last edited by tallguy; 04-02-2007 at 02:41 PM.

  15. #15
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    >> I need one actorGraph for all the movies because this is the Kevin Bacon problem.
    If you need one actorGraph shared between all Movies, then there is a simple solution to this whole problem that doesn't require pointers, shared_ptrs or anything else we've discussed.

    Make the actorGraph static, not mutable. Making it static means that there will be one and only one actorGraph in the entire program. I think this is what you want. If it is static, there will be no copying, so your copying problem will go away as well.

    If I'm misunderstanding and you want separate actorGraphs for each movie, then let me know and I'll comment on the shared_ptr issue.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Getting an error with OpenGL: collect2: ld returned 1 exit status
    By Lorgon Jortle in forum C++ Programming
    Replies: 6
    Last Post: 05-08-2009, 08:18 PM
  2. An error is driving me nuts!
    By ulillillia in forum C Programming
    Replies: 5
    Last Post: 04-04-2009, 09:15 PM
  3. Making C DLL using MSVC++ 2005
    By chico1st in forum C Programming
    Replies: 26
    Last Post: 05-28-2008, 01:17 PM
  4. Connecting to a mysql server and querying problem
    By Diod in forum C++ Programming
    Replies: 8
    Last Post: 02-13-2006, 10:33 AM
  5. Couple C questions :)
    By Divx in forum C Programming
    Replies: 5
    Last Post: 01-28-2003, 01:10 AM