gpt4 book ai didi

C++(有点)工厂

转载 作者:行者123 更新时间:2023-11-28 03:01:10 30 4
gpt4 key购买 nike

我看过很多关于 C++ 工厂的帖子,但到目前为止我还没有看到解决我的问题的解决方案。 (虽然我可能遗漏了一些东西。)

示例控制台应用程序:

#include <memory>
#include <map>
#include <iostream>

using namespace std;

class ResourceManager;

/// abstract base class
class Identity
{
public:
int Id() const { return _id; }

/// make this an abstract class
virtual ~Identity() = 0 {}

protected:
Identity() { _id = _nextId++; }

private:
int _id;
static int _nextId;
};

int Identity::_nextId = int();

/// derived classes
class Component : public Identity
{
friend class ResourceManager;
public:
~Component() { }
};

class Entity : public Identity
{
friend class ResourceManager;
public:
~Entity() { }
};


class ResourceManager
{
public:
template<typename T>
T& Create()
{
auto ptr = std::make_shared<T>();
auto id = ptr->Id();

_resources[id] = std::move(ptr);
return *dynamic_pointer_cast<T>(_resources[id]);
}

private:
std::map<int, std::shared_ptr<Identity>> _resources;
};



int main(int argc, char *argv[])
{
cout << "Factory test" << endl;

ResourceManager r;

auto& e = r.Create<Entity>();
cout << "e.id = " << e.Id() << endl;

Entity e2;
cout << "e2.id = " << e2.Id() << endl;

Component c;
cout << "c.id = " << c.Id() << endl;

std::getchar();
}

我需要确保只有 ResourceManager 可以实例化 Entity、 Component 以及从它们派生的任何类。

我已经查看并将 ResourceManager 作为友元类添加到 Identity, 并将构造函数设为私有(private)或 protected ,但没有成功。 (这可能是一条死胡同,或者只是我这边的一个实现问题。)

有什么建议吗?

更新和编辑

用可编译示例替换了代码。虽然 Identity() 的构造函数受到保护,但我仍然可以直接实例化派生类。

最佳答案

以下应该有效:

friend class ResourceManager; 应该在每个派生类中。( friend 不继承)。

class ResourceManager;

/// abstract base class
class Identity
{
public:
int Id() const { return _id; }

/// make this an abstract class
virtual ~Identity() = 0;

// Forbid any copy
Identity(const Identity&) = delete;
Identity(const Identity&&) = delete;
Identity& operator = (const Identity&) = delete;
Identity& operator = (Identity&&) = delete;

protected:
Identity() { _id = _nextId++; }

private:
int _id;
static int _nextId;
};

// empty destructor
Identity::~Identity() {}

int Identity::_nextId = 0;

/// derived classes
class Component : public Identity
{
friend class ResourceManager;
public:
~Component() { }
protected:
Component() = default;
};

class Entity : public Identity
{
friend class ResourceManager;
public:
~Entity() { }
protected:
Entity() = default;
};


class ResourceManager
{
public:
template<typename T>
T& Create()
{
std::unique_ptr<T> ptr(new T);
T& res = *ptr;

_resources[ptr->Id()] = std::move(ptr);
return res;
}

/// TODO: need to make sure that resource ID is actually of type T
/// and that _resources contains ID.

template<typename T>
T* Get(int id)
{
auto it = _resources.find(id);
if (it == _resources.end()) {
return nullptr;
}
return dynamic_cast<T*>(it->second.get());
}

private:
std::map<int, std::unique_ptr<Identity>> _resources;
};

请注意,由于 ResourceManager 拥有我将 std::shared_ptr 更改为 std::unique_ptr 的资源。我用无效 ID 修复了 ResourceManager::Get

关于C++(有点)工厂,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20818973/

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