【发布时间】:2011-02-17 09:14:00
【问题描述】:
我目前正在实现一个系统,其中包含许多类的代表对象,例如客户端、业务、产品等。标准业务逻辑。正如人们所期望的那样,每个类都有许多标准属性。
我有一长串基本相同的要求,例如:
- 能够检索所有行业为制造业的企业。
- 能够检索所有位于伦敦的客户
类业务有属性sector,客户有属性location。显然这是一个关系问题,在伪 SQL 中看起来像:
SELECT ALL business in business' WHERE sector == manufacturing
不幸的是,插入数据库不是一种选择。
我想要做的是有一个单一的通用聚合函数,其签名将采用以下形式:
vector<generic> genericAggregation(class, attribute, value);
其中 class 是我要聚合的对象的类,attribute 和 value 是感兴趣的类属性和值。在我的示例中,我将向量作为返回类型,但这不起作用。可能更好地声明相关类类型的向量并将其作为参数传递。但这不是主要问题。
如何接受类、属性和值的字符串形式的参数,然后将它们映射到通用对象聚合函数中?
由于不发布代码是不礼貌的,下面是一个虚拟程序,它创建了一堆富有想象力的类的对象。包括一个特定的聚合函数,它返回 B 对象的向量,其 A 对象等于在命令行中指定的 id,例如..
$ ./aggregations 5
它返回所有A对象'i'属性等于5的B。见下文:
#include <iostream>
#include <cstring>
#include <sstream>
#include <vector>
using namespace std;
//First imaginativly names dummy class
class A {
private:
int i;
double d;
string s;
public:
A(){}
A(int i, double d, string s) {
this->i = i;
this->d = d;
this->s = s;
}
~A(){}
int getInt() {return i;}
double getDouble() {return d;}
string getString() {return s;}
};
//second imaginativly named dummy class
class B {
private:
int i;
double d;
string s;
A *a;
public:
B(int i, double d, string s, A *a) {
this->i = i;
this->d = d;
this->s = s;
this->a = a;
}
~B(){}
int getInt() {return i;}
double getDouble() {return d;}
string getString() {return s;}
A* getA() {return a;}
};
//Containers for dummy class objects
vector<A> a_vec (10);
vector<B> b_vec;//100
//Util function, not important..
string int2string(int number) {
stringstream ss;
ss << number;
return ss.str();
}
//Example function that returns a new vector containing on B objects
//whose A object i attribute is equal to 'id'
vector<B> getBbyA(int id) {
vector<B> result;
for(int i = 0; i < b_vec.size(); i++) {
if(b_vec.at(i).getA()->getInt() == id) {
result.push_back(b_vec.at(i));
}
}
return result;
}
int main(int argc, char** argv) {
//Create some A's and B's, each B has an A...
//Each of the 10 A's are associated with 10 B's.
for(int i = 0; i < 10; ++i) {
A a(i, (double)i, int2string(i));
a_vec.at(i) = a;
for(int j = 0; j < 10; j++) {
B b((i * 10) + j, (double)j, int2string(i), &a_vec.at(i));
b_vec.push_back(b);
}
}
//Got some objects so lets do some aggregation
//Call example aggregation function to return all B objects
//whose A object has i attribute equal to argv[1]
vector<B> result = getBbyA(atoi(argv[1]));
//If some B's were found print them, else don't...
if(result.size() != 0) {
for(int i = 0; i < result.size(); i++) {
cout << result.at(i).getInt() << " " << result.at(i).getA()->getInt() << endl;
}
}
else {
cout << "No B's had A's with attribute i equal to " << argv[1] << endl;
}
return 0;
}
编译:
g++ -o aggregations aggregations.cpp
如果你愿意:)
而不是实现一个单独的聚合函数(即示例中的 getBbyA()),我希望有一个通用聚合函数,它考虑所有可能的类属性对,以便满足所有聚合要求......并且在事件附加属性稍后添加,或附加聚合要求,这些将自动考虑。
所以这里有一些问题,但我正在寻求深入了解的主要问题是如何将运行时参数映射到类属性。
我希望我已经提供了足够的细节来充分描述我正在尝试做的事情......
【问题讨论】:
-
你能修改类吗? (如果你不能,你会遇到麻烦。)
-
@Beta:不一定,也可以考虑为这些访问定义 Function 对象。有很多可能性。
-
@Matthieu M.:我不明白。我只能想到两种方法来做到这一点,而无需为每个类的每个字段编写单独的例程:1)修改类或 2)使用宏 [不寒而栗]。我很乐意学习另一种方法......
-
我们的想法是为每个类(示例)注册一个对象,它将类作为参数,然后有一个方法
getattr(name)将字段的值作为字符串返回(或如果不存在此类字段,则为 Null/Void 值)。它确实需要为每个班级做额外的工作,但来自外部。从封装的角度来看更好,因为您只能访问公共字段。
标签: c++ class mapping attributes aggregation