2017-11-07 10 views
0

current_userポインタはSystem.cppの関数内で動作しますが、後でリセットされます。 current_userは、switch文で呼び出されたときに関数createUser(string name)内で設定されたときにローカルに更新されているようです。しかし、私が関数の外でそれを呼び出そうとすると、まったく更新されていないようです。何が起こっているか完全にはわからない。current_userポインタがリセットされるのはなぜですか?

MAIN.CPP

#include <iostream> 
#include "System.h" 
#include "User.h" 

using namespace std; 

int main() 
{ 
    System s; 
    s.run(); 

// Works 
User a("Test"); 
User b("Test 2"); 
User c("Test 3"); 

User* current = &a; 

cout << "The current user is: " << current->getName() << endl; 

current = &b; 

cout << "Now it's: " << current->getName() << endl; 

current = &c; 

cout << "The final current user is: " << current->getName() << endl; 

// Does not work 
    cout << "Current user: " << s.getCurrentUser()->getName() << endl; 
} 

System.h

#ifndef SYSTEM_H 
#define SYSTEM_H 

#include "User.h" 
#include "Group.h" 
#include "MessageBuffer.h" 
#include "Banner.h" 
#include <iostream> 
#include <vector> 

class System 
{ 
    public: 
     System(); 
     char validInput(std::string inputIn); 
     bool validUsername(std::string nameIn); 
     bool userExists(std::string nameIn); 
     void createUser(std::string nameIn); 
     void run(); 
     User* getCurrentUser(); 

    private: 
     User* current_user; 
     std::vector<User> user_list; 
     std::vector<Group> group_list; 


}; 

#endif // SYSTEM_H 

System.cpp

// Program 1: TigerBook Social Network 
// File: System.cpp 
// Description: Class Implimentation of the System Class. Instantiates objects that must be initialized and handles 
//  basic user screw-ups (choosing and option out of bounds). 

#include <iostream> 
#include "System.h" 

using namespace std; 

// Function: Default System Constructor 
// Inputs: None 
// Description: Default constructor for the class. 
System::System() 
{ 

} 

User* System::getCurrentUser() 
{ 
    return current_user; 
} 
// Function: validInput 
// Inputs: string inputIn 
// Outputs: char value of input at 0 
// Description: Determines whether the input is valid. 
char System::validInput(string inputIn) 
{ 
     if (inputIn.length() == 1) 
     { 
      return inputIn[0]; 
     } 

     else 
     { 
      return '0'; 
     } 
} 

// Function: validUsername 
// Inputs: string username 
// Outputs: true if valid, false if not 
// Description: Determines whether the username is valid 
bool System::validUsername(string nameIn) 
{ 
    if (nameIn.empty() || nameIn.length() < 2 || (nameIn.find_first_not_of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") != string::npos)) 
    { 
     cerr << "\n\t*** ERROR: Invalid user name, please try again! ***" << endl; 
     return false; 
    } 

    else 
    { 
     return true; 
    } 
} 

// Function: userExists 
// Inputs: string username 
// Outputs: true if exists, false if not 
// Description: Determines whether the username exists in user_list. 
bool System::userExists(string nameIn) 
{ 
    return false; 
} 

// Function: createUser 
// Inputs: string username 
// Outputs: void 
// Description: Creates new user and adds it to user_list. 
void System::createUser(string nameIn) 
{ 
User u(nameIn); 
user_list.push_back(u); 
current_user = &u; 
} 

// Function: run 
// Inputs: None 
// Outputs: void 
// Description: Program driver, handles basic user input and screw-ups 
void System::run() 
{ 
    //current_user = NULL; 

    Banner banner("The TigerBook Social Network!"); 
    cout << banner.getBanner() << endl; 

    bool quit = false; 
    string input; 

    while(!quit) 
    { 
     cout << "\nCreate new user (n), Broadcast (b), Multicast (m), Unicast (u), Wall page (w), Home page (h), Create new group (g), " << endl; 
     cout << "Join a group (j), Switch user (s), Quit (q)\n" << endl; 

     cout << "Choose an option: "; 
     getline(cin, input); 

     if (current_user == NULL && (input != "N" && input != "n" && input != "Q" && input != "q")) 
     { 
      cerr << "\n\t*** ERROR: There is no current user, please create a new user! ***" << endl; 
      continue; 
     } 

     switch (validInput(input)) 
     { 
      // Create new user 
      case 'N': 
      case 'n': 
      { 
       string username; 

       cout << "\nPlease enter user name: "; 
       getline(cin, username); 

       if (!validUsername(username)) 
       { 
        continue; 
       } 

       else if (userExists(username)) 
       { 
        cerr << "\n\t*** ERROR: The user \"" + username + "\" already exists, please try again! ***" << endl; 
        continue; 
       } 

       else 
       { 
        createUser(username); 
        cout << "\nCurrent user: " << getCurrentUser()->getName() << endl; // test current_user 
       } 

       break; 
      } 

      case 'B': 
      case 'b': 
      { 

       break; 
      } 

      case 'M': 
      case 'm': 
      { 

       break; 
      } 

      case 'U': 
      case 'u': 
      { 

       break; 
      } 

      case 'W': 
      case 'w': 
      { 

       break; 
      } 

      case 'H': 
      case 'h': 
      { 

       break; 
      } 

      case 'G': 
      case 'g': 
      { 

       break; 
      } 

      case 'J': 
      case 'j': 
      { 

       break; 
      } 

      case 'S': 
      case 's': 
      { 

       break; 
      } 

      case 'Q': 
      case 'q': 
      { 
       quit = true; 
       banner.setBanner("Thank you for using TigerBook Social Network!"); 
       cout << banner.getBanner() << endl << endl; 
       break; 
      } 

      default: 
      { 
       cerr << "\n\t*** ERROR: Invalid input, please try again! ***" << endl; 
      } 
     } // End of switch statement 
    } // End of loop 
} 

User.h

#ifndef USER_H 
#define USER_H 

#include <string> 

class User 
{ 
    public: 
     User(); 
     User(std::string nameIn); 
     std::string getName(); 
     void setName(std::string nameIn); 

    private: 
     std::string name; 
}; 

#endif // USER_H 

User.cpp

// Program 1: TigerBook Social Network 
// File: User.cpp 
// Description: Class implementation for User class 

#include "User.h" 

using namespace std; 

// Constructor (Default) 
User::User() 
{ 
    //ctor 
} 

// Constructor 
// Inputs: string that sets name 
// Description: Constructs user object and assigns its name. 
User::User(string nameIn) 
{ 
    name = nameIn; 
} 

// Function: setName 
// Inputs: string that sets name 
// Outputs: void 
// Description: Sets name of user object. 
void User::setName(string nameIn) 
{ 
    name = nameIn; 
} 

// Function: getName 
// Inputs: none 
// Outputs: Name of user 
// Description: Returns the name of the user object. 
string User::getName() 
{ 
    return name; 
} 
+0

あなたが 'CURRENT_USER =&u'が、そう' current_user'はへのポインタとして設定されている ')(システム::のcreateUser'に/ペースト 'User.h' –

+0

をコピーしてくださいしたがって、関数を終了すると、(定義されていない動作で)無効になります。代わりに 'new_'を介してヒープに' current_user'を割り当てようとしてください。 –

答えて

1

あなたが持っている:

void System::createUser(string nameIn) 
{ 
    User u(nameIn); 
    user_list.push_back(u); 
    current_user = &u; 
} 

をここでは、ローカル変数へのポインタを格納しています。関数が復帰するとすぐにポインタがぶら下がりポインタになります。関数が返された後にオブジェクトにアクセスするためにcurrent_usrを使用すると、未定義の動作が発生します。

あなたは使用することができます。

void System::createUser(string nameIn) 
{ 
    User u(nameIn); 
    user_list.push_back(u); 
    current_user = &(user_list.back()); 
} 

でも、それは非常に壊れやすいです。 user_listのオブジェクトを慎重に管理すると機能します。

より良いオプションは、オブジェクトへのポインタをまったく格納しないことです。あなたは、例えば、使用することができます

User* System::getCurrentUser() 
{ 
    if (user_list.empty()) 
    { 
     return nullptr; 
    } 
    return &(user_list.back()); 
} 
+0

うわー、私は分かりませんでした。新しいユーザーをヒープに割り当ててから、逆参照によってベクトルに追加することをお勧めします。 –

関連する問題