2014-11-23 2 views
1

상속 목적을위한 포인터 벡터를 사용하고 있으며 모든 동작을해야하지만 벡터에서 개체를 삭제하는 데 문제가 있습니다.C++ 포인터의 벡터에서 요소 지우기

내가 쉽게 컴파일하고 실행하기위한 메이크과 함께 모든 소스 파일이있는 Github에서의 요점을 만든

:

나는 은행 클래스가 : 기본적으로 여기

https://gist.github.com/anonymous/7c689940992f5986f51e

문제입니다 (계정 데이터베이스 구조 인 캡슐화 된 계정 *에 유의하십시오.)

class Bank 
{ 
private: 
    Database<Account> m_acctDb; 
    Database<User> m_userDb; 
    int m_accountCounter; 
    int m_userCounter; 
public: 
    Bank(); 
    ~Bank(); 

    // Accessor Methods. 
    int getAccountCounter() const; 
    int getUserCounter() const; 
    int getNumAccounts() const; 
    int getNumUsers() const; 
    Database<Account> getAccountDatabase() const; 
    Database<User> getUserDatabase() const; 
    User *getUser (int userId); 
    Account *getAccount (int accountId); 
    std::vector<ChequingAccount> getChequingAccounts() const; 
    std::vector<SavingsAccount> getSavingsAccounts() const; 
    std::vector<Manager> getManagers() const; 
    std::vector<Customer> getCustomers() const; 
    std::vector<Maintenance> getMaintenance() const; 

    // Mutator Methods. 
    void addChequing (int userId, double balance = 0, std::string name = 
      ""); 
    void addSavings (int userId, double balance = 0, 
      std::string name = ""); 
    void addCustomer (std::string firstName, std::string lastName, 
      std::string password, std::string username); 
    void addManager (std::string firstName, std::string lastName, 
      std::string password, std::string username); 
    void addMaintenance (std::string firstName, std::string lastName, 
      std::string password, std::string username); 
    void deleteAccount (int accountId); 
    void deleteUser (int userId); 
}; 

나는 포인터의 벡터 생성과 같은 mplate 데이터베이스 클래스 : 내 은행에서

template<class T> 
    class Database 
    { 
     protected: 
      std::vector<T*> m_database; 
     public: 
      Database(); 
      virtual ~Database(); 
      std::vector<T*> getDatabase() const; 
      void add (T *Object); 
      bool del (int id); 
    }; 

를, 내가 계정과 같은 정의 개체를 추가하고 :

class Account 
{ 
    protected: 
     int m_id, m_userId, m_type; 
     double m_balance; 
     std::string m_name; 
     std::vector<std::string> m_history; 
public: 
    Account (int id, int userId, double balance = 0, 
      std::string name = ""); 
    virtual ~Account(); 

    // Accessor Methods. 
    int getId() const; 
    int getUserId() const; 
    int getType() const; 
    double getBalance() const; 
    std::string getName() const; 
    std::string getDetails() const; 
    std::vector<std::string> getHistory() const; 

    // Mutator Methods. 
    void setName (std::string name); 
    void depositFunds (double amount); 
    virtual bool withdrawFunds (double amount); 
}; 

/* 
* Chequing account type 
*/ 
class ChequingAccount : public Account 
{ 
    public: 
     ChequingAccount (int id, int userId, double balance = 0, 
       std::string name = "") : 
       Account(id, userId, balance, name) 
     { 
      // Chequing account type. 
      m_type = CHEQ; 

      // If no name was given. 
      if (name == "") 
      { 
       // Give account a generic name. 
       m_name = "Chequing Account #" + std::to_string(id); 
      } 
      else 
      { 
       m_name = name; 
      } 
     } 

     ~ChequingAccount() 
     { 
     } 

     virtual bool withdrawFunds (double amount); 
}; 

/* 
* Savings account type 
*/ 
class SavingsAccount : public Account 
{ 
    public: 
     SavingsAccount (int id, int userId, double balance, std::string name) : 
       Account(id, userId, balance, name) 
     { 
      // Savings account type. 
      m_type = SAVE; 

      // If no name was given. 
      if (name == "") 
      { 
       // Give account a generic name. 
       m_name = "Savings Account #" + std::to_string(id); 
      } 
      else 
      { 
       m_name = name; 
      } 
     } 

     ~SavingsAccount() 
     { 
     } 
}; 

내가 계정 개체를 추가하고를, 같은 은행에, 기본 계정 클래스에서 클래스를 파생 주로 Chequing/저축 계정 :

/* 
* Adds a new chequing account to the bank database. 
*/ 
void Bank::addChequing (int userId, double balance, std::string name) 
{ 
    m_acctDb.add(new ChequingAccount(++m_accountCounter, userId, balance, name)); 
} 

/* 
* Adds a new savings account to the bank database. 
*/ 
void Bank::addSavings (int userId, double balance, std::string name) 
{ 
    m_acctDb.add(new SavingsAccount(++m_accountCounter, userId, balance, name)); 
} 

이 모두 제대로 작동하고, 나는 데이터베이스와 m에서 물체를 끌어 당길 수 있어요 내가 좋아하는 방식으로 발랐다.

/* 
* Deletes the specified account from the bank database. 
*/ 
void Bank::deleteAccount (int accountId) 
{ 
    std::vector<Account*> db = m_acctDb.getDatabase(); 
    std::vector<Account*>::iterator it = db.begin(); 
    cout << "Searching for account " << accountId << endl; 
    while (it != db.end()) 
    { 
     if ((*it)->getId() == accountId) 
     { 
      cout << "Found account 1" << endl; 
      // Delete selected account. 
      delete (*it); 
      it = db.erase(db.begin()); 
     } 
     else ++it; 
    } 
} 

내가 모든 기능을 테스트 할 수있는 작은 테스트 파일 생성 : 여기

int main() 
{ 
    Bank bank; 

    cout << "Num accounts in bank: " << bank.getNumAccounts() << endl << endl; 

    cout << "Adding accounts to bank..." << endl; 
    bank.addChequing(1, 1500.0, "testchq"); 
    bank.addSavings(1, 2000.0, "testsav"); 

    cout << "Num accounts in bank: " << bank.getNumAccounts() << endl; 
    for (int i = 0; i < bank.getNumAccounts(); ++i) 
    { 
     if (bank.getAccount(i + 1) == NULL) cout << "Account is NULL" << endl; 
     else 
     { 
      cout << bank.getAccount(i + 1)->getDetails() << endl; 
     } 
    } 
    cout << endl; 

    cout << "Deleting account 1..." << endl; 
    bank.deleteAccount(1); 
    cout << endl; 

    cout << "Num accounts in bank: " << bank.getNumAccounts() << endl; 
    for (int i = 0; i < bank.getNumAccounts(); ++i) 
    { 
     if (bank.getAccount(i + 1) == NULL) cout << "Account is NULL" << endl; 
     else 
     { 
      cout << bank.getAccount(i + 1)->getDetails() << endl; 
     } 
    } 
} 

과 내가 파일을 실행 한 후 얻을 출력되는 문제는 다음과 같은 정의 된, 삭제 함께 :

Num accounts in bank: 0 

Adding accounts to bank... 
Num accounts in bank: 2 
Account #1 [C] testchq $1500.000000 
Account #2 [S] testsav $2000.000000 

Deleting account 1... 
Searching for account 1 
Found account 1 

Num accounts in bank: 2 
Account #1 [C] [C] $1500.000000 
Account #2 [S] testsav $2000.000000 

보시다시피 파생 된 계정 클래스를 올바르게 추가하고 개체 조각을 사용하지 않고 파생 형식을 유지합니다. 삭제 기능에서는 삭제 기능이 삭제할 계정을 찾은 것을 볼 수 있습니다. 문제는 계정 1을 삭제해야하지만 계정 이름을 삭제 한 것입니다 (Account #1 [C] [C] $1500.000000Account #1 [C] testchq $1500.000000).

여기에서 내가 겪고있는 문제점은 무엇입니까? 나는 또한 이것을하는 나의 방법에 관하여 확신 할 수 없다, 그래서 개선을위한 어떤 제안든지 중대하게 평가 될 것입니다.

미리 감사드립니다.

답변

3

당신은 사본에서 계정을 삭제하고 있습니다 :

사용 현황이 원하는, 그래서 당신은, 실제 데이터베이스에서 삭제해야
std::vector<T*> getDatabase() const; 

std::vector<Account*> db = m_acctDb.getDatabase(); 

:

std::vector<T*>& getDatabase(); 
const std::vector<T*>& getDatabase() const; 

std::vector<Account*>& db = m_acctDb.getDatabase(); 
+0

안녕 @Barry, 답변 해주셔서 감사합니다. 내가해야하는 변경 사항을 명확히하기 위해 Database.h의 getDatabase() const의 서명을'const std :: vector & getDatabase() const; '로 변경해야합니다. 그리고'const vector '를 반복 할 때'const_iterator'를 사용해야합니까? 나는 그것으로 무엇을 전달 하는가?지우기()'함수? 나는 그것을 통과 시키려고 노력했다. ('it = db.erase (it);'). 그러나 그것은 나에게 오류를주고 나는 패스해야 할 것을 확신하지 못한다. 감사! – user3745117

+0

@ user3745117 아니요, const가 아닌 참조를 반환해야합니다. 수정해야 할 것이기 때문입니다. 그것은 당신의 오래된 서명이'const' 함수라는 것입니다. 여전히'const' 함수를 갖고 싶다면 const ref를 반환하는 별도의 함수 여야합니다. – Barry

+0

명확히 해 주셔서 감사 드리며 완벽하게 작동했습니다! :)이 질문은 원래 질문보다 조금 더 많으므로이 질문에 답할 필요는 없지만, 빠른 누락으로 인해 메모리 누수와 디자인면에서 문제가 있습니까? 다시 한 번 도와 주셔서 감사합니다. – user3745117

관련 문제