为什么我的current_user指针重置?

时间:2017-11-07 07:07:18

标签: function c++11 pointers

current_user指针在System.cpp的函数内工作,但之后重置。当current_user在switch语句中调用时,它在函数createUser(string name)中设置时似乎在本地更新。但是,当我尝试在函数外部调用它时,它似乎根本没有更新。不完全确定发生了什么。

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;
}

1 个答案:

答案 0 :(得分: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());
}