对于带有元素的类,可以替代联合
alternative to union for classes with ctors
我有一个关于c++设计的问题。
我正在为一个HW赋值构建一个树。树的实现非常简单。基本上它是一个模板化的类
template <typename TYPE, typename KEY>
class Tree
{
public:
void Insert(TYPE& node);
void Remove(TYPE& node);
TYPE& Find (KEY key);
//etc.
};
到目前为止只是背景。现在,稍后当我使用Tree时,我有一个Employee类,我希望有2棵树,但一次使用ID作为键,另一次使用Salary作为键,但我不想复制数据。显然我需要实现两个不同的比较函数。我的第一次尝试是这样做的:
class Employee
{
public:
int ID;
float Salary;
};
enum COMPARE_RESULT
{
LESS_THAN = -1,
EVEN = 0,
GREATER_THAN = 1
}
template
class IComparable
{
public:
virtual COMPARE_RESULT Compare (const T& other) const = 0;
};
class EmployeeCompareByID : public Employee, public IComparable
{
public:
Compare (const T& other) const
{
//Compare IDs and return result
}
};
class EmployeeCompareBySalary : public Employee, public IComparable
{
public:
Compare (const T& other) const
{
//Compare Salaries and return result
}
};
typedef union
{
Employee employeeData;
EmployeeCompareByID employeeCompareByID;
EmployeeCompareBySalary employeeCompareBySalary;
}EmployeeUnion;
//finally the main would do something like this:
int main()
{
//first tree key is by ID
Tree empTreeByID;
//second tree key is by salary
Tree empTreeBySalary;
EmployeeUnion emp;
emp.employeeData.ID = 1;
emp.employeeData.Salary = 1000.11;
empTreeByID.Insert(emp.employeeCompareByID);
empTreeBySalary.Insert(emp.employeeCompareBySlary);
//the same emp is referenced in both trees. Each by it's relevant member in union
}
但是这种方法失败了,因为我的Employee类有构造函数、复制构造函数和操作符重载,所以在Employee上定义联合是不可能的。此外,这种方法要求Tree实现对TYPE执行static_cast模板参数到IComparable,这对我来说似乎很好。
另一个可能的解决方案是传递一个函数指针给Tree构造函数,并带有指向该实例的相应Compare函数的指针,但在我看来,这似乎是一个不优雅的解决方案,并且可能相当混乱,以后很难调试。
在谷歌上搜索使用类联合的限制,我发现一个帖子建议解决一个类似的问题,使用转换操作符重载,但没有扩展太多。
我相信这是一个相当普遍的问题,有一个共同的设计解决方案,我只是不知道。
欢迎有任何想法或评论
代码中的实际问题是,您试图将比较数据结构和雇员数据结构放在同一个对象中。它们应该是不同的对象,像这样:
template<class T> class ICompare {
virtual bool Compare(const T &a, const T &b) const=0;
};
显然你需要修改Tree构造函数:
template<class T> class Tree {
Tree(const ICompare<T> &c) : c(c) { }
...
const ICompare<T> &c;
};
比较器不是雇员——它不应该继承。创建单独的比较器,查看传递的Employee
引用并对它们进行比较。
如果您不想复制数据,请使用例如boost::shared_ptr
或以下方法:
list<Employee> ActualData;
map<int, list<Employee>::iterator> EmployeeByID;
map<float, list<Employee>::iterator> EmployeeBySalary;
要查看:
map<int, shared_ptr<Employee> > EmployeeByID;
map<float, shared_ptr<Employee> > EmployeeBySalary;
我怀疑除了在非常低级别的代码中有很好的联合用例。这几乎总是一个出价的想法,因为它可以招致许多不希望的效果(谷歌一点看到这一点)。
这里,您只想要一个树,其中键在一种情况下是ID,在另一种情况下是工资,并且项目是指向员工的指针。
这样你就不会重复雇员,你只是有几个指向雇员的指针,这很好。这两棵树是分开的,这是理想的。(如果你想添加任何其他树,你可以做同样的事情,而不改变其他树的类型。)
如前所述,我还将使用多索引容器和某种智能指针指向员工对象。类似于(从我的头顶,未测试!):
typedef multi_index_container<
boost::shared_ptr < Employee >,
indexed_by<
// sort by unique id
ordered_unique < tag < EmployeeIdTag >, member < Employee,int,&Employee::m_id > >,
// sort by salary
ordered_non_unique < tag < EmplyeeSalaryTag >, member < Employee,int,&Employee::m_salary > >
>
> EmployeeContainer;
typedef EmployeeContainer::index<EmployeeIdTag>::type EmployeeContainerById;
typedef EmployeeContainer::index<EmplyeeSalaryTag>::type EmployeeContainerBySalary;
http://www.boost.org/doc/libs/1_46_1/libs/multi_index/doc/examples.html例二
- 使用不带参数的函数访问结构元素
- 带结构的二维矢量:如何存储元素
- 如何在 Arduino 字符串的开头添加元素.类似于 JS unshift();
- C++函数,它将数组、谓词和运算符作为参数,并将运算符应用于满足谓词的数组元素
- 将函数应用于元组中的每个元素,将每个元素强制转换为类型包中的不同类型,然后作为参数包传递
- 将函数应用于特征矩阵中的所有元素,而无需循环
- 检查元素是否存在于二维矢量中
- 就地合并,类似于 std::vector 中的元素
- 仅当元组中存在该类型时,将功能应用于元组元素
- 复制 std::vector,但将 lambda 应用于每个元素
- 将二进制操作员应用于数组中的每个元素
- C 如何将函数应用于向量元素
- 为什么 OpenCL 嵌套循环仅适用于某些元素
- 是否可以将std ::函数应用于特征矩阵的每个元素
- 以编程方式推断出枚举的大小,独立于其元素的价值
- 独立于元素内存管理的向量上的函数
- 将相同的功能应用于不同大小的N数组的每个元素
- C++用于将函数应用于连续元素的算法
- 如何相对于其他元素过滤矢量元素
- CUDA功能只适用于某些元素