我的class
包含map
。之前,有两个maps
,一个带有char
密钥,另一个带有string
密钥。我创建了一个class
,其中包含enum
和union
以及两个构造函数,一个来自char
,另一个来自string
,重载了比较运算符并使用了{{1}作为关键。
但我一直在想。这可以通过巧妙地使用继承来解决吗?
修改
我的课程是这样的:
class
后来我可以用它fe。那样:
class A
{
enum B
{
Ax, Ay
} b;
union C
{
X x;
Y y;
} c;
public:
A(X x) : b(Ax), c(x) {}
A(Y y) : b(Ay), c(y) {}
bool operator<(A& rhs)
{
if(this->b == rhs.b)
{
if(this->b == Ax) return this->c.x < b.c.x;
if(this->b == Ay) reutrn this->c.y < b.c.y;
}
// if the "type" is different, I assume values are different
// and all I need is any strong ordering, actual order doesn't matter
return this->b < rhs.b;
}
};
现在使用大括号,我可以使用各种class Q
{
// ...
public:
Q(vector<A> v)
{
// don't worry about this code, I haven't figured out how c++11 for each
// works exactly yet, but it's not important, I can do that myself
for each (auto a in v)
{
// ...
}
}
};
初始化Q
,我可以从A
或A
创建不同的char
。
我的类string
通过包含union来获得比较一种类型的键所需的实际数据,以及用于比较不同类型键的枚举。具有虚基类和两个子类的基本继承树将导致每个实例包含相同数量的信息 - 不同的内部变量将扮演联合的角色,不同的实际类将扮演枚举的角色。但是,如果不违反任何重要原则,我就无法想出办法。
答案 0 :(得分:2)
一旦后者在您的编译器中可用,为什么不使用#include <boost/variant.hpp>
#include <string>
#include <map>
#include <iostream>
int main()
{
using Key = boost::variant<char, std::string>;
using Value = int; // whatever
std::map<Key, Value> map;
map['A'] = 1;
map["B"] = 2;
map["A"] = 3;
for (auto&& key_value : map)
{
std::cout << key_value.first << " => " << key_value.second << '\n';
}
}
或std::variant
?
感觉这是解决问题的最自然的方法,并使代码具有可读性:
A => 1
A => 3
B => 2
输出:
{{1}}
答案 1 :(得分:1)
尽管通常可以使用继承来简化union
代码,但是当您需要混合的对象组以获得了解所有其他实现的行为时,它并没有多大帮助。
您可以创建一个基类,并有两个子类 - 用于基于字符串的键和基于字符的键。但是,基于字符串的键的比较运算符必须知道如何使用基于字符的键,并且基于字符的键的运算符必须知道如何使用基于字符串的键。在类似的情况下,代码变成了单一的&#34;,使单个类替代更可取。
在您的情况下,暴露两个构造函数并在内部维护string
的类应该是一个简单的替代方法:
class MyKey {
string key;
int subtype;
public:
MyKey(const string& s) : key(s), subtype(1) {}
MyKey(char c) : key(1, c), subtype(2) {}
bool operator<(MyKey& other) {
return subtype==other.subtype
? (key < other.key)
: (subtype < other.subtype);
}
};