Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++;:跟踪类对象 我定义了C++类,并且在我的程序运行时创建了该类的许多对象。_C++_Oop - Fatal编程技术网

C++;:跟踪类对象 我定义了C++类,并且在我的程序运行时创建了该类的许多对象。

C++;:跟踪类对象 我定义了C++类,并且在我的程序运行时创建了该类的许多对象。,c++,oop,C++,Oop,我需要一个get\u object\u by\u name方法 这就是我在python中要做的: class Person(): all_instances = [] def __init__(self, name, age): self.name = name self.age = age self.all_instances.append(self) @classmethod def get_obj_by_na

我需要一个
get\u object\u by\u name
方法

这就是我在python中要做的:

class Person():
    all_instances = []
    def __init__(self, name, age):
        self.name = name
        self.age = age 
        self.all_instances.append(self)
    @classmethod
    def get_obj_by_name(cls, name):
        for obj in cls.all_instances:
            if obj.name == name:
                return obj 


我如何在C++中实现?

< P> C++没有Python中的代码< > ALLUBLUTION<代码>的特性。 你必须自己处理这件事

首先,您需要将类的不同对象存储在一个容器中(例如,
std::list persons

get\u object\u by\u name
如下所示

Person & get_object_by_name(const std::string &name) {
    for (auto & person : persons) {
        if (person.get_name() == name) {
            return person;
        }
    }
}
Person
需要有一个方法
get\u name()
。或者,您可以重载操作符
==
get\u object\u by\u name
需要访问
Person
。因此最好将它们放入类中

class Persons{
  public:
    Person & get_object_by_name(const std::string &name);
    // constructor to fill persons
    // method to fill persons

  private:
    std::list<Person> persons;
};
班级人员{
公众:
Person&get\u object\u by\u name(const std::string&name);
//建造师负责填充人员
//填补空缺的方法
私人:
std:列出人员;
};

正如SPD所指出的,容器的选择并非无足轻重。如果您使用and
std::vector
,它会随着时间的推移而增长,这将导致重新分配,因此所有返回的引用都将无效。

您可以使用无序映射(哈希映射,需要C++11)或映射(rbtree)来模拟Python的字典

类对象{
public://为了简单起见,您将需要使用ctor、getter和setter。
std::字符串名;
//其他领域。。。
};
std::无序的_映射对象;
对象*通过名称获取对象(const std::string&name){
自动映射迭代器=objects.find(name);
返回map\u iterator==objects.end()?nullptr:map\u iterator->second;
}
请记住,在C++中没有自动内存管理功能,因此您需要将对象存储在某个位置,以防止内存泄漏或指针悬空。如果您希望
对象拥有对象,请将原始指针替换为唯一的\u ptr(或共享的\u ptr,具体取决于用例):

std::无序映射对象;

>P>正如其他答案中所提到的,C++中不存在这种特性,必须自己编写代码。您已经有了一些例子,说明如何通过定义外部存储类和自己跟踪对象来实现它。下面是另一种将对象跟踪的责任委托给<代码>的方法。关于
类本身。其他假设:

  • 您只能使用参数化构造函数(或删除
    explicit
    关键字以使其转换构造函数)
  • 人名必须是唯一的
  • 您要小心,不要试图对堆栈上分配的对象调用
    delete

用ValGrn.VC++验证的例子:你可以在<代码> STD中记录::MAP< <代码>静态STD::vector < /COD>成员变量。Python中的类变量在C++中是等价的,作为<代码>静态< /代码>成员,但你确实想这样做吗?听起来像是一个糟糕的设计,应该用另外的方式解决。(但不是真的重复)回答。@Sky它违反了单一责任规则-你的类做了它设计用来做的事情,并且它存储了自己的实例。而且这种实现背后的用例通常也有一种不好的味道。我不是说它一定不好(缺少这方面的信息),但值得仔细检查。

class Person
{
public:
  /* for example simplifity I delete all the other CTors */
  Person() = delete;
  Person(const Person& other) = delete;
  Person(Person&& other) = delete;
  explicit Person(const std::string& name): name_(name)
  {
    std::cout << "Person(" << name_ << ");" << std::endl;
    if (all_instances_.count(name_) != 0)
    {
      std::cout << "Person with name " << name_ << " already exists" << std::endl;
      throw std::runtime_error("Person with that name already exists");
    }
    all_instances_.emplace(std::make_pair(name_, this));
  }
  ~Person()
  {
    std::cout << "~Person(" << name_ << ");" << std::endl;
    all_instances_.erase(name_);
  }
  static Person* get_person_by_name(const std::string& name)
  {
    if (all_instances_.count(name) == 0)
    {
      std::cout << "Person with name " << name << " does not exist" << std::endl;
      return nullptr;
    }
    return all_instances_.find(name)->second;
  }

private:
  static std::map<std::string, Person*> all_instances_;
  std::string name_;
};

std::map<std::string, Person*> Person::all_instances_;


int main(int argc, char* argv[])
{
  Person p1("person1");
  try
  {
    Person p2("person1");  // exception
  }
  catch (const std::exception& e)
  {
    std::cout << "Exception: " << e.what() << std::endl;
  }
  {
    Person p3("person3");
    Person* p4 = new Person("person4");
    new Person("person5");  // lost pointer, but later we get it from the map
    delete p4;
    // p3 out of scope
  }
  auto person5 = Person::get_person_by_name("person5");
  delete person5;
  auto person1 = Person::get_person_by_name("person1");
  if (person1) std::cout << "Person1 still exists" << std::endl;
  auto person3 = Person::get_person_by_name("person3");
  if (!person3) std::cout << "Person3 does not exist anymore" << std::endl;
  return 0;
  // p1 out of scope
}
Person(person1);
Person(person1);
Person with name person1 already exists
Exception: Person with that name already exists
Person(person3);
Person(person4);
Person(person5);
~Person(person4);
~Person(person3);
~Person(person5);
Person1 still exists
Person with name person3 does not exist
Person3 does not exist anymore
~Person(person1);