一个理论问题。如果不清楚我在问什么,请非常友好地评论它而不会阻止我,如果有必要,我会改写。
假设您已经创建了一个类并且已经创建了该类的100个实例。 (只有名称和唯一ID号的简单类)
现在你想在那个类中找到一个对象,但你拥有的只是idnumber。你需要这个名字。
您用于实例化该特定实例的类的对象名,您不能再知道了。
该函数如何根据您看起来的id号来查找名称?
我希望有人有一个代码,告诉我这是如何工作的。
答案 0 :(得分:0)
首先,我希望你的内存分配和解除分配实际上有一个非常严重的心理模型。例如,您是否了解堆与堆栈的区别?你了解什么是复制构造函数以及“rule of three”的含义是什么?如果不了解这些基本概念,您将无法为您的问题创建任何合理的解决方案。
所以,当你说“已经制作了100个该类的实例”时,究竟是怎么回事呢?你仍然将它们放在内存中却无法枚举?
如果您确实拥有内存中的对象但没有简单的方法来枚举它们,那么显而易见的解决方案是创建一个允许枚举对象(“注册表”)的显式数据结构。以下代码仅通过两种方式解决了基本情况:基于矢量和基于地图。最有可能的是,您不仅需要创建“全局注册表”,还需要创建工厂方法或其他内容的特定注册表。还有一些代码可能会为您提供一些想法:
<强> IdAndName.h 强>
#pragma once
#include <string>
#include <map>
#include <vector>
#include <algorithm>
using std::string;
using std::map;
using std::vector;
using std::find;
class IdAndName {
public:
const int id;
const string name;
IdAndName(int id, string name);
~IdAndName();
private:
static vector<IdAndName*> registryVec;
static void addToVecRegistry(IdAndName* obj);
static void removeFromVecRegistry(IdAndName* obj);
public:
static IdAndName* findByIdInVec(int id);
private:
static map<int, IdAndName*>registryMap;
static void addToMapRegistry(IdAndName* obj);
static void removeFromMapRegistry(IdAndName* obj);
public:
static IdAndName* findByIdInMap(int id);
};
<强> IdAndName.cpp 强>
#include "IdAndName.h"
IdAndName::IdAndName(int id, string name): id(id), name(name) {
// 1) What is correct behavior if there is already such id for other object?
// For example what about values created by copy-constructor?
// 2) What happens if the "id" field is not "const" and can be changed (especially in the map registry case)?
addToVecRegistry(this);
addToMapRegistry(this);
}
IdAndName::~IdAndName() {
removeFromVecRegistry(this);
removeFromMapRegistry(this);
}
/////////////////////////////////////////////
vector<IdAndName*> IdAndName::registryVec;
void IdAndName::addToVecRegistry(IdAndName* obj) {
registryVec.push_back(obj);
}
void IdAndName::removeFromVecRegistry(IdAndName* obj){
vector<IdAndName*>::iterator position = find(registryVec.begin(), registryVec.end(), obj);
if (position != registryVec.end()) // end() means the element was not found
registryVec.erase(position);
}
IdAndName* IdAndName::findByIdInVec(int id) {
// or use std::find_if
for (vector<IdAndName*>::iterator it = registryVec.begin(); it != registryVec.end(); ++it){
if ((*it)->id == id)
return *it;
}
return NULL; // What is correct behavior if there is no such object?
}
/////////////////////////////////////////////
map<int, IdAndName*> IdAndName::registryMap;
void IdAndName::addToMapRegistry(IdAndName* obj){
registryMap[obj->id] = obj; // What is correct behavior if there is already such id for other object?
}
void IdAndName::removeFromMapRegistry(IdAndName* obj){
registryMap.erase(obj->id);
}
IdAndName* IdAndName::findByIdInMap(int id) {
return registryMap[id]; // What is correct behavior if there is no such object?
}
<强> Test.cpp的强>
#include "IdAndName.h"
#include <cassert>
#include <iostream>
using std::cout;
using std::endl;
void initStack(){
for(int i = 0; i<10; i++){
IdAndName val = IdAndName(i, string("IdAndName #") + std::to_string(i));
}
}
void testStack() {
initStack();
IdAndName* pId2Vec = IdAndName::findByIdInVec(2);
// cout << "Found Vec " << pId2Vec->name <<endl; // bad idea
assert(pId2Vec == NULL);
IdAndName* pId2Map = IdAndName::findByIdInMap(2);
// cout << "Found Map " << pId2Map ->name <<endl; // bad idea
assert(pId2Map == NULL);
}
void initHeap(){
for(int i = 0; i<10; i++){
IdAndName* val = new IdAndName(i, string("IdAndName #") + std::to_string(i));
}
}
void testHeap() {
initHeap();
IdAndName* pId2Vec = IdAndName::findByIdInVec(2);
cout << "Found Vec " << pId2Vec->name <<endl;
IdAndName* pId2Map = IdAndName::findByIdInMap(2);
cout << "Found Map " << pId2Map->name <<endl;
assert(pId2Map == pId2Vec);
}
<强>自我评估强>
testStack和testHeap有什么区别?为什么会得到 NULL和其他工作?为什么行被评为“坏主意”实际上是个坏主意?
基于矢量和基于地图的解决方案有什么区别? 性能?稳定性?副作用
copy-constructor如何影响两种实现的行为?
非const id如何影响两种实现的行为?