具有可以是两种类型之一的数据成员的类
Posted
技术标签:
【中文标题】具有可以是两种类型之一的数据成员的类【英文标题】:Class with data member that can be one of two types 【发布时间】:2020-03-31 17:58:44 【问题描述】:最好用一些代码来解释:
class MyClass
public:
MyClass(const std::string& d1, const std::string& d2, const std::vector<AorB>& d3) : data1(d1), data2(d2), data3(d3)
std::string getData1();
std::string getData2();
std::vector<AorB> getData3();
private:
std::string data1;
std::string data2;
std::vector<AorB> data3;
int main()
MyClass myClassA("d1", "d2", std::vector<A>());
MyClass myClassB("d1", "d2", std::vector<B>());
A myA = myClassA.getData3();
B myB = myClassB.getData3();
当使用 boost 变体或 boost any 时,此工作流“几乎”有效,但我要避免的是调用 boost::get 以获取实际类型的 getData3 结果。换句话说,我不希望 MyClass 的使用者必须知道 A 或 B 是否存储在 data3 中。我只是希望他们能够调用 getData3(),它是在创建时传递的任何类型。
我认为可以通过具有模板专业化/递归继承的模板来实现,但我不太清楚如何让它发挥作用。也许它看起来像这样?
class MyClass
public:
template <typename AorB>
MyClass(const std::string& d1, const std::string& d2, const std::vector<AorB>& d3) : data1(d1), data2(d2), data3(d3)
std::string getData1();
std::string getData2();
template <typename AorB>
std::vector<AorB> getData3();
private:
std::string data1;
std::string data2;
template <typename AorB>
std::vector<AorB> data3;
int main()
MyClass myClassA<A>("d1", "d2", std::vector<A>());
MyClass myClassB<B>("d1", "d2", std::vector<B>());
A myA = myClassA.getData3();
B myB = myClassB.getData3();
但是这行不通,因为我们不能有非静态模板类成员。
【问题讨论】:
您是要复制std::vector<std::variant<A, B>>
还是std::variant<std::vector<A>, std::vector<B>>
?
A
和 B
是否继承自一个共同的基础?如果不是,我真的不明白“我不希望 MyClass 的消费者必须知道 A 或 B 是否存储在 data3 中”,因为一旦他们调用 getData3
,用户就知道它是什么类型
【参考方案1】:
要执行您正在尝试的操作,您需要将模板作为一个整体应用于MyClass
,例如:
template <typename AorB>
class MyClass
public:
MyClass(const std::string& d1, const std::string& d2, const std::vector<AorB>& d3) : data1(d1), data2(d2), data3(d3)
std::string getData1();
std::string getData2();
std::vector<AorB> getData3();
private:
std::string data1;
std::string data2;
std::vector<AorB> data3;
;
int main()
MyClass<A> myClassA("d1", "d2", std::vector<A>());
MyClass<B> myClassB("d1", "d2", std::vector<B>());
A myA = myClassA.getData3();
B myB = myClassB.getData3();
【讨论】:
哎呀,这是一个微不足道的修复,现在感觉有点愚蠢。是的,这正是我想要的,谢谢!【参考方案2】:您可以在此处使用 union 来设置创建时想要的任何数据类型以及检索时获得的数据类型。 Union 为其所有成员分配一个公共内存位置。联合占用的内存将大到足以容纳联合的最大成员。
union AorB
A;
B;
;
然后在上面的程序中使用
【讨论】:
使用union
将不允许从A
或B
返回getData3
,除非您建议返回联合,这让调用者知道哪个是活动的会员
在这种情况下,使用union
比使用variant
没有任何好处以上是关于具有可以是两种类型之一的数据成员的类的主要内容,如果未能解决你的问题,请参考以下文章