gpt4 book ai didi

c++ - 对基类和派生类使用静态容器

转载 作者:太空狗 更新时间:2023-10-29 19:39:13 34 4
gpt4 key购买 nike

我正在尝试构建一个 [base+derived] 类的对象容器(准确地说是 std::map),它是一个静态变量,嵌入其中基类,以便从它派生或从它的子类派生的每个其他对象最多只有 1 个列表。此外,如果没有创建对象,我仍然可以通过其他友好(静态)函数访问该列表。

这是代码 -

#include <iostream>
#include <string>
#include <unordered_map>

class A{

std::string id;
static std::unordered_map<std::string, A*> list;

public:

A(std::string _i): id(_i){}
static void init(){
// doSomeProcessing or let's just call clear() for now
list.clear();
}
static void place(std::string _n, A* a){
list[_n] = a;
}
virtual void doSomething(){std::cout << "DoSomethingBase\n";}
};

std::unordered_map<std::string, A*> A::list = {};

class B : public A{

std::string name;

public:

B(std::string _n):name(_n), A(_n){}
void doSomething(){std::cout << "DoSomethingDerived\n";}
};


int main() {
A::init();
A::place("b1", new B("b1"));
A::place("a1", new A("a1"));
return 0;
}

代码编译成功但是,我的脑海中有两件事,我可能做错了,一个是主要问题,另一个是小问题。

Major - 指针作为 std::map 的值?我确定我还没有完全掌握它们,但我正在努力学习。我知道它们不会在这里被删除,但我应该怎么做呢?在析构函数中?或者让程序完成......(不好,对吧?)

次要 - 使用静态成员?我从人们那里听说静态变量由于某些未知原因是不好的,除非必要,否则不应使用。它们甚至从某些早期版本的 cpp 中删除。是对的吗?但是我的选择是什么...在 main() 中创建它。

我可能在这里犯的任何其他错误。


编辑 - 我提供了一个示例场景,以便通过以下示例阐明我的意图。

Let's say I've an employee class and some more specific jobs eg editor, writer, developer that are still derived from employees. However there might exist instance of base class employee too, since there might be employees who aren't cateogrised yet, but will be soon.

假设这是一项要求,但我愿意接受更改。我正在使用该静态 std::map,因此只需要它的一个实例,它在所有基类和派生类中都是统一的。我对单例模式等不太熟悉,但我会很乐意在未来学习它。

最佳答案

主要:使用托管指针。这是基于 unique_ptr 的代码修改版本:

class A{
// ...
static std::unordered_map<std::string, std::unique_ptr<A>> list;

// ...
template< class T, class... Args >
static
// enable only A-based objects for T via the return type
typename std::enable_if<std::is_base_of<A, T>::value>::type
place(std::string _n, Args&&... args)
{
list.emplace(_n, std::make_unique<T>(std::forward<Args>(args)...));
}
// ...
};

std::unordered_map<std::string, std::unique_ptr<A>> A::list = {};

class B : public A{

// ...
// corrected a warning here: bases should be constructed before members
B(std::string _n):A(_n), name(_n){}
// ...
};

int main() {
A::init();
A::place<B>("b1", "b1");
A::place<A>("a1", "a1");
// maybe, the second argument is now redundant
// you can remove it and call in place
// std::make_unique<T>(_n, std::forward<Args>(args)...)
return 0;
}

我修改了place让它负责分配——使用make_unique这是 C++14,你可以使用 new T{std::forward<Args>(args)...}反而。新place函数是一个 variadic template关注make_unique原型(prototype)。

正如 Adam Martin 在评论中所建议的那样, enable_if 可以用来限制类型 T到继承 A 的对象.

由 Jarod42 编辑,您应该使用 forward references尊重调用时传递的值类别 place .

我用了 emplace 而不是 operator[]以避免不必要的复制或移动操作。

另一种选择是使用 shared_ptr如果您需要复制指针。实现将是相似的。

关于c++ - 对基类和派生类使用静态容器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39333445/

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