Thread: main file cannot access private member declared in class header file

  1. #1
    Registered User
    Join Date
    Apr 2014
    Posts
    10

    main file cannot access private member declared in class header file

    Hi everyone...

    I am currently doing the assignment about linked list. Here are some details information about what I am doing..

    This program is C++ and should run on Visual Studio 2010.
    And it contains three file, two datastructure header and one main cpp file.

    This program is trying to arrange and show some sports records. The main program which contain the functions such as reading the result text file(each result text file contain several records of athletes), removing a file, arranging the totalresult and printing it out. And the main program is already given and I cannot overwrite it.


    But when I finished and try to build the solution and run it, I am not able to run the program and it give me somethings like these...

    warning C4172: returning address of local variable or temporary
    error C2248: 'Datastructure1:atastructure1' : cannot access private member declared in class 'Datastructure1'
    see declaration of 'Datastructure1:atastructure1'
    see declaration of 'Datastructure1'
    This diagnostic occurred in the compiler generated function 'Result::Result(const Result &)'

    And I have tried to comment each function part of the header file and see if can run or not. But I still fail to do so.

    Here are my codes...
    Code:
    #ifndef DATASTRUCTURE1_H
    #define DATASTRUCTURE1_H
    
    class Datastructure1 {
        
      
    public:
        
      Datastructure1( );
      ~Datastructure1( );
    
    
      int size( ){
          int i=0;
              while(result[i]!= NULL){
                  i++;
              }
              return i;      
         
      }
    
      bool add( int new_elem ){
          for(int i=0;i<size();i++){
              if(result[i]==NULL){
                  result[i] = new_elem;
                  return true;
              }
          }
            return false;
    
      }
    
      int& operator []( int index ){
          if(index>0 && index<(size()+1) ){
            return result[index-1];
          }
          int a =0;
          return (int &)a;
      }
    
    private:
        int result[20];
      // copying forbidden
      Datastructure1(const Datastructure1&);
      // no assignment
      Datastructure1& operator=(const Datastructure1&);
    
    };
    
    #endif
    Code:
    #ifndef DATASTRUCTURE2_H
    #define DATASTRUCTURE2_H
    
    
    #include "datastructure1.h"
    
    
    using namespace std;
    
    struct Result {
    
      string name;
      int totalresult;
      Datastructure1 results;
      Result *next;
    };
    
    class Datastructure2 {
    
      
    public:
    
    
      Datastructure2( );
    
      ~Datastructure2( );
    
      int size( ){
          int count=0;
          Result* p = head; 
            while (p != NULL) 
            { 
                ++count; 
                p = p->next; 
            }
            return count;
    
      }
    
    
      bool add( Result* new_r, int index ){
          Result *temp;
          temp = head;
    
        for(int c=1;  c<(index-1); c++){
              temp = temp->next;
        }
        if(temp->next!=NULL){
            Result *temp2;
            temp2=temp->next;  
            temp->next = new_r;
            temp->next->next=temp2;
            return true;
        }else if(temp->next==NULL){
            temp->next = new_r;
            return true;
        }else{return false;}
        
    
      }
    
    
      Result& operator[]( int index ){
        int i;
        Result *currPtr;
        currPtr = head;
        for(i = 1; i < index; i++){
            currPtr = currPtr->next;
        }
        return  *currPtr;
    
        
           
      }
    
      void remove( int index ){
        int i;
        Result *currPtr;
        currPtr = head;
        for(i = 1; i < index; i++){
            currPtr = currPtr->next;
        }
            currPtr->next = currPtr->next->next;
        
    
      }
    
      void removeAll( ){
          Result* temp1 = head;
            while(temp1!=NULL) 
                {   
                    head->next = temp1->next;
                    temp1->next = NULL;
                    delete(temp1);
                    temp1 = head->next;
                }
      }
      
    private:
        Result *head;
        Result *tail;
        
    
    
      // copying forbidden
      Datastructure2(const Datastructure2&);
      // no assignment
      Datastructure2& operator=(const Datastructure2&);
    
    };
    
    #endif
    There are two header files and look quite long. They are all some linked list functions . I have read and learn linked list data structure before I complete this programs. However, when I complete the functions required, the function cannot be compile....
    Please help me and I have worked on this for whole weeks already..
    thank you again

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    It would help if you showed the error message including the line number.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    Apr 2014
    Posts
    10
    Quote Originally Posted by laserlight View Post
    It would help if you showed the error message including the line number.
    thanks for reminding me.
    Here are the contents:
    Here are the whole contents of error boxes..


    1>c:\xxx\visual studio 2010\projects\assignment2\assignment2\datastructur e1.h(55): warning C4172: returning address of local variable or temporary
    1>c:\xxx\visual studio 2010\projects\assignment2\assignment2\datastructur e2.h(21): error C2248: 'Datastructure1:atastructure1' : cannot access private member declared in class 'Datastructure1'
    Code:
    Datastructure2::Result {
    
      string name;
      int totalresult;
      Datastructure1 results;
      Result *next;
    };
    1> c:\xxx\visual studio 2010\projects\assignment2\assignment2\datastructur e1.h(61) : see declaration of 'Datastructure1:atastructure1'
    1> c:\xxx\visual studio 2010\projects\assignment2\assignment2\datastructur e1.h(15) : see declaration of 'Datastructure1'
    Code:
    private:
    	int result[20];
      // copying forbidden
      Datastructure1(const Datastructure1&);
      // no assignment
      Datastructure1& operator=(const Datastructure1&);
    
    };
    1> This diagnostic occurred in the compiler generated function 'Result::Result(const Result &)'

  4. #4
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    First, the warning stems from the snippet:
    Code:
      int& operator []( int index ){
          if(index>0 && index<(size()+1) ){
            return result[index-1];
          }
          int a =0;
          return (int &)a;
      }
    in Datastructure 1. If you cannot find a match, you should throw an exception. Under no circumstances should you return a reference or a pointer to a local variable. Returning 0 makes no sense either since it can be a valid value (how is the client supposed to distinguish between errors and successes?).

    The error stems from the your Result structure which contains a Datastructure1. Datastructure1 cannot be copied; therefore, Result cannot be copied. But since you didn't disallow it, the compiler tried to create a default copy constructor which copies all members. This generates a compile error because the copy constructor in Datastructure1 is private.
    Solution: Make the copy constructor in Result private or mark it as deleted, i.e.: Result(const Result&) = delete; (requires C++11-compliant compiler).
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  5. #5
    Registered User
    Join Date
    Apr 2014
    Posts
    10
    Quote Originally Posted by Elysia View Post
    First, the warning stems from the snippet:
    Code:
      int& operator []( int index ){
          if(index>0 && index<(size()+1) ){
            return result[index-1];
          }
          int a =0;
          return (int &)a;
      }
    in Datastructure 1. If you cannot find a match, you should throw an exception. Under no circumstances should you return a reference or a pointer to a local variable. Returning 0 makes no sense either since it can be a valid value (how is the client supposed to distinguish between errors and successes?).

    The error stems from the your Result structure which contains a Datastructure1. Datastructure1 cannot be copied; therefore, Result cannot be copied. But since you didn't disallow it, the compiler tried to create a default copy constructor which copies all members. This generates a compile error because the copy constructor in Datastructure1 is private.
    Solution: Make the copy constructor in Result private or mark it as deleted, i.e.: Result(const Result&) = delete; (requires C++11-compliant compiler).
    Oh, I think I know where the problem is. Thank you
    But will I cause any problem if I use this solution to delete?
    As it is part of the Result structure, I want to keep it.

    and where should "Result(const Result&) = delete;" put?
    Sorry if my questions is stupid@@. But I am really confused in these

  6. #6
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    What it will do is disallow you to copy your Result, which is the most sensible solution, if you cannot change Datastructure1.
    Think about it: if you allow Result to be duplicated, what will you do with the Datastructure1 member? You cannot copy it, so does it make sense to be able to make a copy of Result? If it does, then what is their relation to Datastructure1? Is it supposed to be shared between copies of Result? If so, then making changes to one copy of Result will also make changes to the other copy of Result. Is that what you want? If not, it makes no sense to copy a Result.

    You should put
    Result(const Result&) = delete;
    as a public member of your Result structure.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  7. #7
    Registered User
    Join Date
    Apr 2014
    Posts
    10
    Quote Originally Posted by Elysia View Post
    What it will do is disallow you to copy your Result, which is the most sensible solution, if you cannot change Datastructure1.
    Think about it: if you allow Result to be duplicated, what will you do with the Datastructure1 member? You cannot copy it, so does it make sense to be able to make a copy of Result? If it does, then what is their relation to Datastructure1? Is it supposed to be shared between copies of Result? If so, then making changes to one copy of Result will also make changes to the other copy of Result. Is that what you want? If not, it makes no sense to copy a Result.

    You should put
    Result(const Result&) = delete;
    as a public member of your Result structure.
    This is a very clear explanation. I think I know what the exact problem is now.
    I will try to compile it.
    Thank you

  8. #8
    Registered User
    Join Date
    Apr 2014
    Posts
    10
    Quote Originally Posted by Elysia View Post
    What it will do is disallow you to copy your Result, which is the most sensible solution, if you cannot change Datastructure1.
    Think about it: if you allow Result to be duplicated, what will you do with the Datastructure1 member? You cannot copy it, so does it make sense to be able to make a copy of Result? If it does, then what is their relation to Datastructure1? Is it supposed to be shared between copies of Result? If so, then making changes to one copy of Result will also make changes to the other copy of Result. Is that what you want? If not, it makes no sense to copy a Result.

    You should put
    Result(const Result&) = delete;
    as a public member of your Result structure.
    When I put it in Result structure, it shows up these.
    1>c:\xxx\assignment2\assignment2\datastructure2.h( 21): error C2059: syntax error : ';'
    1>c:\xxx\assignment2\assignment2\datastructure2.h( 21): error C2238: unexpected token(s) preceding ';'
    Code:
    struct Result {
    
      string name;
      int totalresult;
    
      Datastructure1 results;
      Result(const Result&) = delete;
    
      Result *next;
    };
    I am using VS2010 and is it causing any problem?
    many thanks

  9. #9
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Elysia's solution works for C++11, but not for older versions of C++. Your compiler is probably not C++11.

    The approach for a pre-C++11 compiler is to change
    Code:
    struct Result    //   C++11 version
    {
       Result(const Result&) = delete;
    };
    to
    Code:
    struct Result    //   pre-C++11 version
    {
         private:
              Result(const Result&);
    };
    This makes the copy constructor inaccessible, except to your Result class or to friends. Don't define (i.e. implement) the copy constructor. That ensures you will get either a compiler error or a linker error whenever you try to use the copy constructor (i.e. to copy an object).
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  10. #10
    Registered User
    Join Date
    Apr 2014
    Posts
    10
    Quote Originally Posted by grumpy View Post
    Elysia's solution works for C++11, but not for older versions of C++. Your compiler is probably not C++11.

    The approach for a pre-C++11 compiler is to change
    Code:
    struct Result    //   C++11 version
    {
       Result(const Result&) = delete;
    };
    to
    Code:
    struct Result    //   pre-C++11 version
    {
         private:
              Result(const Result&);
    };
    This makes the copy constructor inaccessible, except to your Result class or to friends. Don't define (i.e. implement) the copy constructor. That ensures you will get either a compiler error or a linker error whenever you try to use the copy constructor (i.e. to copy an object).
    But if I make it inaccessible, I cannot use it in the main function.
    As I want to use these two header in the main.cpp

    Here are the main code which is a little bit long. Sorry for this

  11. #11
    Registered User
    Join Date
    Apr 2014
    Posts
    10
    sorry, clean this reply
    Last edited by programkillme; 04-05-2014 at 06:39 AM.

  12. #12
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by programkillme View Post
    But if I make it inaccessible, I cannot use it in the main function.
    As I want to use these two header in the main.cpp
    If you use Elysia's solution, you can't use the copy constructor in the main() function either. They're just different approaches to achieving the same thing.

    Making a class member private does not prevent use of the header in the main() function. It prevents use of the private member.

    You're mixing up your requirements. The point of making a member private (or forcing it not to exist) is to prevent it being used. If an instance of a class should not be copied, you do not want the copy constructor to be used. You can't have your cake and eat it too, by simultaneously specifying that a copy constructor (or anything else for that matter) can be used and that it cannot be used.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  13. #13
    Registered User
    Join Date
    Apr 2014
    Posts
    10
    But Result is the most important part in Datastructure2.h as the information storage and I am going to use it in main.cpp.
    If I use this method to make Result inaccesible, then error cause in main.cpp because main program need to deal with it.
    Sorry for the code above. I have made it better here
    Code:
    int main( ) {                  
        
     
      Datastructure2 tr2;
    
      char command = ' ';
    
      while( true ) {
    
        cin >> command;
        
        // addition
        if( command == 'L' ) {
          
          string file_name = "";
          cin >> file_name;
          
          // read file
          if( !addFile( tr2, file_name ) ) {
        
        cout << "Error in reading file: " << file_name
             << endl;
          }
        }
        // removal
        else if( command == 'P' ) {
          
          string file_name = "";
          cin >> file_name;
          
          // read the file
          if( !removeFile( tr2, file_name ) ) {
        
        cout << "Error in opening file: " << file_name
             << endl;
          }
        }
        
        // print
        else if(  command == 'K' || command == 'T') {
          
          int amount = 0;
          if( !readNumber( amount ) || amount <= 0 || amount > tr2.size( ) ) {
        
        cout << "Incorrect amount!" << endl;
          }
          else if( command == 'K' ) {
        
        print(tr2, amount);
          }
          else {
        printListing(tr2, amount);
          }
        }
        
    
        // quit
        else if( command == 'Q' ) {
          
          tr2.removeAll();
          return EXIT_SUCCESS;    
        }
        
        else {
        
          cout << "Unknown command: " << command << endl;
        }
      }
    }
    Code:
    bool addFile( Datastructure2& tr2, string& file_name ) {
    
      // open the file
      ifstream file( file_name.c_str( ) );
    
      // file not found
      if( !file ) {
    
        return false;
      }
    
      char separator =' ';
      int index = 1;
      string smudge;
      // Create Result structs out of the lines in the file
      while( !file.eof() ) {
        
        Result* new_result = new Result;
        getline(file, new_result->name, ':');
    
        file >> new_result->totalresult;
        int tmp =0;
    
        for( int idx = 0; idx < THROWS; idx++ ) {
    
          file >> separator >> tmp;
          new_result->results.add( tmp );
        }
    
        while(isspace(file.peek())) {
          file.get(separator);
        }
        
        while(index <= tr2.size() &&
          tr2[index].totalresult > new_result->totalresult) {
    
          index++;
        }
        // add new result to database
        tr2.add( new_result, index );
      }
      return true;
    }
    Code:
    bool removeFile( Datastructure2& tr2, string& file_name ) {
    
      // open file
      ifstream file( file_name.c_str( ) );
    
      // file not found
      if( !file ) {
    
        return false;
      }
    
      char separator = ' ';
      int index = 1;
      string name = "";
      int totalresult = 0;
    
      // Go through the file
      while( !file.eof() ) {
        
        getline(file, name, ':');
    
        file >> totalresult;
        int tmp = 0;
    
        for( int idx = 0; idx < THROWS; idx++ ) {
    
          file >> separator >> tmp;
        }
        
        while(isspace(file.peek())) {
          file.get(separator);
        }    
    
        while(index < tr2.size() &&
          tr2[index].totalresult > totalresult) {
    
          index++;
        }
    
        // remove the resultfrom the data
        if( tr2[index].name == name) {
    
          tr2.remove( index );
        }
      }
      return true;
    }
    Code:
    void print( Datastructure2& tr2, int amount ) {
    
      for( int index = 1; index <= amount; index++ ) {
    
        cout << tr2[index].name << " " << tr2[index].totalresult;
    
        for( int jndex = 1; jndex <= THROWS; jndex++ ) {
        
          cout << " " << tr2[index].results[jndex];
        }
        cout << endl;
      }
    }
    Code:
    void printListing( Datastructure2& tr2, int amount ) {
    
      for( int index = 1; index <= amount; index++ ) {
    
        cout << tr2[index].name << " " << tr2[index].totalresult << endl;
      }
    }
    Code:
    bool readNumber( int& number) {
    
      string tmp = "";
      cin >> tmp;
      istringstream ss(tmp);
    
      if(!(ss >> number)) {
    
        return false;
      }
      return true;
    }

  14. #14
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    You're the one who said that DataStructure2 cannot be copied. That is your problem. If it can't be copied, then Result (which contains it) cannot be copied either.

    A consequence of that is that the copy constructor of both DataStructure2 and Result should not be used, and should not be accessible.

    You either need to

    1) Fix DataStructure2 so it can be copied, give it an accessible copy constructor, and allow Result to have a usable copy constructor

    2) Accept that DataStructure2 cannot be copied, so Result cannot be copied and should not have a usable copy constructor. That means you can't do things that involve copying DataStructure2 (or Result).


    There is no halfway point. The two options are mutually exclusive (since the only way to invoke a copy constructor is to create a copy of an object). But you're essentially asking for a way to meet both requirements simultaneously. That is your mistake.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  15. #15
    Registered User
    Join Date
    Apr 2014
    Posts
    10
    Oh, I am getting headache with these.
    But the original code are already be default with these.... let me show you the original code.
    Code:
    #ifndef DATASTRUCTURE1_H
    #define DATASTRUCTURE1_H
    
    // NOTE! none of the operations is allowed to make any changes to
    // the other elements or change their order
    
    // the size of datastructure1 can be limited to 20 elements
    
    class Datastructure1 {
      
    public:
    
      // constructor
      Datastructure1( );
      ~Datastructure1( );
    
      // returns the amount of elements
      int size( );
    
      // adds a new element to the end of the data structure
      // returns true, if the addition was done successfully
      bool add( int new_elem );
    
      // returns a reference to the element at the given index
      // indexing is done between [1 - size]
      int& operator []( int index );
    
    private:
      // copying forbidden
      Datastructure1(const Datastructure1&);
      // no assignment
      Datastructure1& operator=(const Datastructure1&);
    
    };
    
    #endif
    Code:
    #ifndef DATASTRUCTURE2_H
    #define DATASTRUCTURE2_H
    
    #include "datastructure1.h"
    
    
    using namespace std;
    
    struct Result {
    
      string name;
      int totalresult;
      Datastructure1 results;
    };
    
    class Datastructure2 {
      
    public:
    
      // constructor
      Datastructure2( );
    
      // destructore
      ~Datastructure2( );
    
      // returns the size of the data structure
      int size( );
    
      // adds a new element to the data structure
      // returns true if successfull
      bool add( Result* new_r, int index );
    
      // returns a reference to the element at the index
      // indexing is done between [1-size]
      Result& operator[]( int index );
    
      // removes the element at the index
      void remove( int index );
    
      // deletes all elements from the data structure by using delete
      void removeAll( );
    
    private:
      // copying forbidden
      Datastructure2(const Datastructure2&);
      // no assignment
      Datastructure2& operator=(const Datastructure2&);
    
    };
    
    #endif
    And mentioned above, Result data structure is being copyable and be used in main.cpp. So I am really confused that if the instruction given is wrong.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 33
    Last Post: 09-28-2011, 05:17 AM
  2. cannot access private member declared in class
    By newme in forum C++ Programming
    Replies: 7
    Last Post: 11-16-2008, 03:57 PM
  3. private class member access
    By DarkMasterBosel in forum C++ Programming
    Replies: 6
    Last Post: 03-30-2008, 11:37 AM
  4. Replies: 2
    Last Post: 02-14-2008, 02:59 PM
  5. hiding private member in header file
    By Micko in forum C++ Programming
    Replies: 1
    Last Post: 03-30-2004, 08:46 AM