用C++实例化一个新对象

Instantiating a New Object in C++

本文关键字:一个 新对象 对象 C++ 实例化      更新时间:2023-10-16

我是一名学习C++的Java/PHP程序员。

我已经创建了一个名为UserAccountDatabase的类。

我有一个输入文件,有五个名称:

Bob
Sam
Jane
Mark
Ann

我有以下(伪)代码:

UserAccount *ua;
while (reading through the list of names, line by line) {
    ua = new UserAccount(name); // Create a new user based on this name
    Database->add(ua); // Add the user to the database
}
Database->listAllUsers();

输出应该镜像输入文件。相反,我得到了:

Ann
Ann
Ann
Ann
Ann

我想这与指针有关,但我搞不清楚。我认为我已经提供了足够的信息来识别问题,但如果上面的(伪)代码看起来正确,我可以提供更多。

你能提供一个正确实施的例子吗?

这将是一个开始:

#include <string>
#include <vector>
class UserAccount {
public:
    UserAccount(const std::string& name) : d_name(name) {}
    ...
private:
    std::string d_name;
};
class Database {
public:
    Database() : d_accounts() {}
    void add(const UserAccount& account) {
        this->d_accounts.push_back(account);
    }
    ...
private:
    std::vector<UserAccount> d_accounts;
};
void zb() {
    Database db;
    db.add(UserAccount("Bob"));
    ...
}

它与您发布的内容不同,因为向量存储的是UserAccounts的值。无论如何,更多的代码会有所帮助。我最终会删除它,因为它不是一个真正的答案(好吧,也许会在问题定义得更好后更新)。

跟进我的评论。您可能会遇到指针冲突,std::string类将为您提供与Java更相似的行为。

最简单的解决方案是使用字符串strdup()调用。

#include <cstring> // provides C string interface
UserAccount::UserAccount(char *n) {
    name = strdup(n);
}
UserAccount::~UserAcount() {
    // This is older C style, cleanup. Need or the memory will "leak".
    free(name);
    // You could also use: delete[] name;
}

或者,你可以使用std::string,但我将把它留给你的学习过程。有很多关于指针的信息,这将有助于你深入了解指针。

// e.g.
char *str1 = "ann";
char *str2 = "bob";
str1 = str2;
// Both equal "bob".
str1 = "carol";
// Both equal "carol"!

祝你好运。

在C++中,与其他语言不同,您必须明确考虑事物存储在内存中的位置。一个指针告诉你在内存中的什么地方查找。一个类比是告诉你看一本书第124页第5行的第三个字母。如果我的书是用铅笔写的,我可以擦掉那一页上的单词,用其他单词替换,虽然指针会保持不变(也就是说,我看书中的同一位置),但所指的内容会改变。

这就是代码中发生的情况。每次读入一个名称时,都会擦除以前的名称,并将新名称写入同一内存位置。因此,当您在构造函数中传递指针时,您所指向的内存可能会发生变化。

若要解决此问题,您需要制作名称的本地副本。这可以通过使用字符串类来完成,就像@Justin的响应一样。但是,出于教学目的(这段代码有点复杂),以下是您可以在内部分配新内存的方式(字符串类只是为您做这件事):

class UserAccount {
public:
    UserAccount(const char *name)
    {
        m_name = new char[strlen(name)+1];
        strcpy(m_name, name);
    }
    ~UserAccount()
    {
        delete [] m_name;
    }
private:
    char * m_name;
};

请注意,我们现在正在使用析构函数,因为我们已经分配了内存,并且需要在删除类时再次释放它。还要注意,我还没有检查传入的名称是否为null,应该这样做。最后要注意的是,字符串隐式地以null结尾,以告诉您何时到达字符串的末尾。这就是为什么我们必须分配一个大的大小——在字符串的末尾保留null。

正如@Marc所指出的,你也可以使用strdup,但我认为更长的解释和显示内存的显式分配将有助于更好地了解正在发生的事情。

使用STL&算法

U需要一个用户帐户类来存储单个用户的详细信息,数据库类来存储所有用户帐户的详细信息。

使用字符串、stl、算法来提高效率。

满足您需求的菜单驱动程序示例:

#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
class useraccount
{
    string name;
    //other details
public:     
    void get(string str)
    {
        name=str;
    }
    void display()
    {
        cout<<name<<endl;
    }
};
void display_db(useraccount & e)
{
    e.display();
}
void main()
{
    vector<useraccount> database;
    useraccount *ptr;
    int choice;
    string name;    
    do
    {
        cout<<"nn1.Insert n2.Deleten3.Displayn4.Exit nEnter your choice: n";
        cin>>choice;
        switch(choice)
        {
        case 1:
            ptr=new useraccount;
            cout<<"Enter name:n";
            cin>>name;
            ptr->get(name);
            database.push_back(*ptr);
            break;
        case 2:
            database.pop_back();
            break;
        case 3:
            for_each(database.begin(),database.end(),display_db);
            break;
        case 4:
            cout<<"Quiting";
            break;
        default:
            cout<<"wrong choice";
        }
    }while(choice!=4);
}