访问类的对象

时间:2017-02-25 00:26:50

标签: visual-c++

一个理论问题。如果不清楚我在问什么,请非常友好地评论它而不会阻止我,如果有必要,我会改写。

假设您已经创建了一个类并且已经创建了该类的100个实例。 (只有名称和唯一ID号的简单类)

现在你想在那个类中找到一个对象,但你拥有的只是idnumber。你需要这个名字。

您用于实例化该特定实例的类的对象名,您不能再知道了。

该函数如何根据您看起来的id号来查找名称?

我希望有人有一个代码,告诉我这是如何工作的。

1 个答案:

答案 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);
}

<强>自我评估

  1. testStack和testHeap有什么区别?为什么会得到 NULL和其他工作?为什么行被评为“坏主意”实际上是个坏主意?

  2. 基于矢量和基于地图的解决方案有什么区别?     性能?稳定性?副作用

  3. copy-constructor如何影响两种实现的行为?

  4. 非const id如何影响两种实现的行为?