我实际上并不打算在任何地方应用这个设计,但我仍然很好奇如何在C ++中实现这一点,特别是在C ++和#39的情况下缺乏反思。 (我同时学习和试验C ++ 11的功能,所以请在有帮助的地方使用C ++ 11功能。)
我想要达到的几乎是纯粹的化妆品。
我喜欢一个类,它使用引用的成员(根据我的理解,必须在构造期间初始化)将任意数量的矢量绑定到任意数量的向量,但是提供了#34;别名&#34 ;用于作为成员访问这些向量。
举一个最小的例子,我想让它起作用 -
std::vector<int> one;
std::vector<int> two;
std::vector<int> three;
Foo foo(std::make_pair('B', one),
std::make_pair('D', two),
std::make_pair('F', three));
foo.DoSomething();
,其中
class Foo
{
public:
// I'm using variadic templates here for sake of learning,
// but initializer lists would work just as well.
template <typename ...Tail>
Foo(std::pair<char, std::vector<int>&> head, Tail&&... tail) // : ???
{
// ???
}
virtual void DoSomething()
{
D.push_back(42);
std::cout << D[0] << std::endl;
}
private:
std::vector<int> A&, B&, C&, D&, E&, F&, G&; // and so on...
}
也是如此
std::cout << one[0] << std::endl; // outputs 42 from outside the class...
为什么有人想要这样做?好吧,我不想 想要这样做,但我想到的应用程序是这样的。假设我正在构建某种数据分析工具,并且我有客户或操作人员知道基本逻辑和C ++语法,但不了解OOP或CS 101以外的任何东西。事情会变得更顺畅如果他们可以动态编写自己的DoSomething()
,而不是向开发人员传达每一个需求。但是,让他们设置UNIX帐户,教他们如何编译等等是不现实的。因此,我希望建立一个内部网络界面,让他们编写DoSomething()
的正文并配置他们喜欢的数据集&#34;别名&#34;通过大写char
,在提交时,为Foo
的子类生成C ++,它覆盖DoSomething()
,然后构建,运行并返回输出。 (可疑的是特定于&#34;假设,&#34;呃?:-)好吧,这种情况确实存在于我的世界中 - 然而它只是启发了这个想法和探索它的愿望 - 我不喜欢和#39;认为它值得实际实施。)显然,这整个大写char
的考验并非绝对必要,但它是一个很好的接触,因为数据集已经与标准字母相关联,例如 P代表价格,Q代表数量等
说实话,我无法弄清楚我是如何使用引用来完成这项工作的。对于these reasons,我更喜欢使用引用。
有了指针,我想我会这样做 -
class Foo
{
public:
template <typename ...Tail>
Foo(std::pair<char, std::vector<int>*> head, Tail&&... tail)
{
std::vector<int>[26] vectors = {A, B, C, D, E, F, G}; // and so on...
// I haven't learned how to use std::forward yet, but you get the picture...
// And dear lord, forgive me for what I'm about to do...
vectors[tail.first - 65] = tail.second;
}
virtual void DoSomething()
{
D->push_back(42);
std::cout << (*D)[0] << std::endl;
}
private:
std::vector<int> A*, B*, C*, D*, E*, F*, G*; // and so on...
}
但即便如此也不是那么优雅。
有没有办法使用引用并实现这个目标?
有没有办法让这个更通用,例如。使用伪反射方法来避免再次列出所有大写字母?
有关替代设计的任何建议,以更优雅或更紧凑的方式保留主要目标(我所描述的化妆品别名)?
答案 0 :(得分:1)
您可以使用以下内容:
class Foo
{
public:
template <typename ...Ts>
Foo(Ts&&... ts) : m({std::forward<Ts>(ts)...}),
A(m.at('A')),
B(m.at('B'))
// and so on...
{
}
virtual void DoSomething()
{
A.push_back(42);
std::cout << A[0] << std::endl;
}
private:
std::map<char, std::vector<int>&> m;
std::vector<int> &A, &B; //, &C, &D, &E, &F, &G; // and so on...
};
但是这需要给出每个向量,所以
Foo(std::vector<int> (&v)[26]) : A(v[0]), B(v[1]) // and so on...
{
}
或
Foo(std::vector<int> &a, std::vector<int> &b /* And so on */) : A(a), B(b) // and so on...
{
}
似乎更合适。
如果拥有Foo
的班级vector
似乎更简单,那么你就会拥有
class Foo
{
public:
virtual ~Foo() {}
virtual void DoSomething() { /* Your code */ }
std::vector<int>& getA() { return A; }
private:
std::vector<int> A, B, C, D; // And so on
};
并提供getter初始化内部向量。
然后
std::vector<int>& one = foo.GetA(); // or foo.A if you let the members public.