我有一个包含类Obj
实例的应用程序,每个实例都由一个ID整数标识为类成员。对象被排列为顶级对象,嵌套子对象的分支存储在std::vector
中,如下所示:
/* Obj tree with L ID as:
*
* Obj (L 0)
* |
* Obj (L 1)
* |
* Obj (L 2)
*
*/
我已经定义了一个实用程序方法,用于将指针重定向到层次结构中具有给定ID的对象。这是通过从具有子对象的每个对象对实用程序的递归调用来实现的,直到找到对象或已到达层次结构的底部。然后递归应该展开并返回指向应用程序范围的指针。出于这个原因,我已将指针作为引用传递,因此可以在适当的递归调用中进行更改。
源代码如下:
Object类是
// Object class
class Obj {
friend class Utils;
friend class App;
public : Obj(int ID_L) // Overloaded constructor
{
this->ID_L = ID_L;
}
// Public and private IDs
public : int ID_L;
// Vector of sub objects
std::vector<Obj> subObj;
// Add sub-obj method
public : void addSubObj(int num_layers) {
// Add the sub-obj
subObj.emplace_back( this->ID_L + 1);
// Add one underneath if necessary
if (subObj.back().ID_L <= num_layers) {
subObj.back().addSubObj(num_layers - 1);
}
};
};
Utility类是
// Utility class
class Utils {
// Static method to return pointer to obj in the hierarchy
public : static void getObj(Obj*& ObjTree, int ID_L, Obj*& ObjRet) {
// Try match on the top of the tree given
if (ObjTree->ID_L == ID_L) {
ObjRet = ObjTree; // Match found so update pointer and return
return;
} else {
// Loop through array of subObjs on this Obj
for (Obj o : ObjTree->subObj) {
// Create pointer to object in present scope
Obj* O = &o;
// Look for match on this subObj
Utils::getObj(O, ID_L, ObjRet); // Recursvie call passing reference of pointer along and address of present sub-Obj and its children
// If a match found then return the non-null pointer
if (ObjRet != NULL) {
return;
}
}
}
// Specified Obj has not been found in the tree
return;
}
};
应用程序类是
// Application class
class App {
public : void run () {
// Create object tree as above
Obj TopObj(0); // Top level obj
TopObj.addSubObj(2); // Left side branch
// Create pointer to Obj to do further stuff with
Obj* _o;
// Create pointer to tree
Obj* Tree = &TopObj;
// Loop over all desired ID combos and return pointer to appropriate Obj in hierarchy
for (int l = 0; l <= 2; l++) {
// Null the pointer in preparation for next Obj
_o = NULL;
// Try to fetch a particular Obj from ObjTree
Utils::getObj(Tree, l, _o);
// If pointer is not null then Obj has been found so try to read IDs from it
if (_o != NULL) {
std::cout << "FOUND -- L" << l << " : reading ID from pointer as L" << _o->ID_L << " : " << _o << std::endl;
}
}
}
};
切入点在这里:
// Entry point
int main(int argc, char* argv[]) {
// Start application
App a;
a.run();
}
调试时我已经将指针_o
的值写入屏幕,我可以看到它在找到对象时发生变化,然后在递归展开时保持其值。但是,当尝试访问它指向的对象将ID打印到应用程序范围内的屏幕时,这些数字是垃圾。当在层次结构中找到2层深层或更多时,就会出现这种情况。只有向下钻取一个级别时 才能工作。
由于我将指针作为引用传递,因此我确信它们将通过范围进行,但似乎并非如此,因为它似乎超出了范围。
任何人都可以看到此实现的问题,并可能建议改进此类对象检索实用程序的实现吗?
答案 0 :(得分:2)
在
for (Obj o : ObjTree->subObj) {
Utils::getObj(&o, ID_L, ID_R, ObjRet);
您制作了Obj
的副本,而ObjRet
可能会在离开范围后悬挂指针。
改为使用:
for (Obj& o : ObjTree->subObj) {
Utils::getObj(&o, ID_L, ID_R, ObjRet);