我正在实现一个类,其中每个实例都有一个句柄,该句柄将完全依赖于成员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;
};
理想情况下,如果类型为handleA
,则存在TypeA
,如果类型为handleB
,则存在TypeB
,如果类型为{{handleC
,则存在TypeC
1}}。但是,我认为应该有一个更好的设计模式。否则,我拥有的类型越多,unique_ptr
在类Foo
中占用的union
就越多。我知道c++
可能是一个很好的解决方案,但我想知道是否存在可扩展性更高的c++11
或self.get_queryset()
解决方案。由于Foo可能以虚拟方式用于其他派生类,这将采用不同的构造函数,我不是在寻找模板解决方案。
答案 0 :(得分:1)
我一直在讨论这些要求,并发现这里要解决的基本问题是:如何在运行时选择类型。
其他所有东西都可以通过一些模板魔法来解决 - 在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();
}
请注意,以这种方式使用不完整类型(例如我的句柄)时,请注意以下几点: