gpt4 book ai didi

c++ - 向上移动对象层次结构

转载 作者:太空宇宙 更新时间:2023-11-04 13:08:43 25 4
gpt4 key购买 nike

您好,我正在处理的程序中有一些不错的对象树层次结构。我遇到了从下到上沟通的问题。我现在如何设置它是在每个构造函数中我传递一个对创建新对象的对象的引用。简单的结构如下所示:
[ Controller ] -> [世界] -> [对象]

向上一层(从世界到 Controller 或从对象到世界)是可以的。但是问题开始出现的地方是当我尝试上升 2 层时。这是我如何设置它的简化结构:

Controller .h:

#include "World.h"

Class Controller {
public:
Controller() {
_worlds.push_back(World(*this));
)

void update() { // Called on a loop from main program loop
_worlds[0].update(); // Calls update of active world, in this case world[0]
}

vector<World> _worlds;

Camera _camera; // class with checkIfInView function
}

世界.h:

#Include "Object.h"

Class Controller;

Class World {
World(Controller& ref) : _controller(ref) {
_objects.push_back(Object(*this));
_controller._camera.doStuff(); // works OK
}

void update() {
for (auto& i : _objects)
i.update();
}

vector<Object> _objects;
Controller& _controller;
}

对象.h:

Class World;

Class Object {
Object(World& ref) : _world(ref) {}
void update();

World& _world;
}

对象.cpp:

#include "Controller.h"
#include "World.h"

void Object::update() {
_world._controller._camera.checkIfInView(*this); // Read access violation
}

Controller 持有一个负责显示内容的相机对象。我需要的是一种让对象调用 checkIfInView 以了解它们是否应该呈现的方法。有没有其他方法可以做到这一点或解决它?

编辑:更新代码。

最佳答案

问题

让我们看看您的 nice 链,从 Controller 构造函数开始。因为它是层次结构的顶级对象,所以它是构造的开始。我想在 main() 中你有类似

的东西
Controller c;  

这将导致构造函数被调用:

 Controller() {
_worlds.push_back(World(*this)); // !!!
}

World(*this) 将创建一个新的临时世界,您将把它插入 Controller 的世界 vector 中。临时对象仅在它出现的表达式的时间内存在。

然后临时世界将被构建

World(Controller& ref) : _controller(ref) {  // ref to controller is kept 
_objects.push_back(Object(*this)); // ouch!!!
_controller._camera.doStuff(); // works OK
}

现在将创建一个指向 *this world 的对象。哎哟!!还记得那个世界是暂时的吗?在构造结束时,它将被删除,以便所有对象都将引用一个不再存在的 C++ 对象,因此在您的情况下恰好产生段错误的 UB。

解决方案的开始

您的设计非常精致。如果找不到更安全的设计模式,请三思。如果您仍然想朝这个方向努力,请避免使用临时项创建对象:而是创建动态分配的对象。

Controller() {
_worlds.push_back(*new World(*this)); // !!! risk of leakage
}

下一步是使用指针而不是引用:

Controller() {
_worlds.push_back(new World(*this)); // risk of leakage
}

当然,您需要相应地更改其余代码才能使用指针。

下一步是选择共享指针:这避免了泄漏的风险:

Controller() {
_worlds.push_back(make_shared<World>(*this)); // risk of leakage
}

在你的代码的改编中,你需要在你的 vector 中的 shared_ptr 和 weak_ptr 之间有所区别,它指的是对象,weak_ptr 指向 parten 对象,以表明父对象现在由子对象共享,但是由另一个对象。

更好的解决方案?

我警告你这不是小菜一碟。一旦有了指示,就需要处理 rule of 3对于每个类(class)。

许多问题源于:

1) 嵌套构造 -> 可能值得考虑 builder 设计模式2)混合静态对象和动态创建对象的风险,永远不知道哪种是父对象。 -> 可能值得使用 protected /私有(private)构造函数并使用工厂方法来确保所有对象始终是动态对象。

关于c++ - 向上移动对象层次结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40941783/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com