gpt4 book ai didi

c++ - union 成员(member)根据不同类型排他性

转载 作者:行者123 更新时间:2023-11-28 05:38:50 24 4
gpt4 key购买 nike

我正在实现一个类,其中每个实例都有一个句柄,该句柄将完全依赖于成员 type。不同的类型与不同的句柄相关联。

enum class Type {
TypeA, TypeB, TypeC;
};

class HandleA { ... };
class HandleB { ... };
class HandleC { ... };

class Foo {
public:
Type type;
std::unique_ptr<HandleA> handleA;
std::unique_ptr<HandleB> handleB;
std::unique_ptr<HandleC> handleC;
};

理想情况下,如果类型为TypeA,则handleA存在,如果类型为TypeB,则handleB存在,并且如果类型为 TypeC,则 handleC 存在。但是,我相信应该有更好的设计模式。否则,我的类型越多,Foo类中占用的unique_ptr就越多。我知道 union 可能是一个很好的解决方案,但我想知道是否存在可扩展性更高的 c++c++11 解决方案。由于 Foo 可能以虚拟方式用于将采用不同构造函数的其他派生类,因此我不是在寻找模板化解决方案。

最佳答案

我一直在研究需求,发现这里要解决的基本问题是:如何在运行时选择类型。

其他一切都可以通过一点模板魔法来解决——当 Foo 本身不应该是模板时失败了。

然后,任何克服这个问题的技巧(我们可以用成员函数指针做一些令人惊奇的事情)似乎只需要重新实现已经免费提供给我们的 VTable 间接虚拟函数。出于这种考虑,我倾向于遵循@RobK 的评论:

#include <iostream>
#include <memory>
#include <string>

enum class Type { TypeA, TypeB, TypeC };

class Handle
{
public:
// virtual ~Handle() = default; // if any subclass is not empty
virtual std::string sing() const = 0; // purely virtual function
};
class HandleA : public Handle { public: std::string sing() const { return "Aaha"; } };
class HandleB : public Handle { public: std::string sing() const { return "Behe"; } };
class HandleC : public Handle { public: std::string sing() const { return "Cehe"; } };

class Foo
{
Type type;
std::unique_ptr<Handle> handle;

public:
constexpr Foo(Type newType) : type{newType}, handle()
{
switch(newType) // establishes the mapping between Type and Handle-subclass
{
case Type::TypeA: this->handle.reset(new HandleA()); return;
case Type::TypeB: this->handle.reset(new HandleB()); return;
case Type::TypeC: this->handle.reset(new HandleC()); return;
}
}

// virtual function call automatically resolves to used subclass
void showHandle() const { std::cout << this->handle->sing() << std::endl; }
};

int main()
{
Foo fooA(Type::TypeA);
Foo fooB(Type::TypeB);
Foo fooC(Type::TypeC);

fooA.showHandle();
fooB.showHandle();
fooC.showHandle();
}

请注意,在以这种方式使用不完整类型(例如我的 Handle)时,需要牢记以下几点:

  1. 如果任何子类定义了自己的非静态成员对象,则 Handle 和所有 子类都必须接收声明的虚拟析构函数。
    • 如果没有,此类子类的对象销毁是不完整的,并且会泄漏内存。
    • 就像 Handle 中被注释掉的析构函数一样,它们可以被默认。
  2. 不要覆盖纯虚函数,例如我的 Handle::sing 然后调用它会立即终止程序。

关于c++ - union 成员(member)根据不同类型排他性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37621883/

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