我正在尝试确定可以使用哪种模式以更“组合”的方式和更少“命令式”的方式声明C ++类。
我正在尝试编写一个包含多个MyDescriptor
成员的类。 MyDescriptor
需要由MyHost
类的构造函数初始化,并在对MyHost
成员的引用上进行迭代。
是否有一种方法可以声明不需要单独添加类成员对容器的引用的MyHost
实现?
class MyDescriptor {
public:
string name;
string fqn;
MyHost(string n) : name(n) {}
void init(string host) {
fqn = host + ":" + name;
}
void do_thing() {
// subclasses to special things.
}
}
class MyHost {
public:
vector<MyDescriptor*> descriptors;
string name
MyHost(string n, vector<MyDescriptor*> d) : name(n),descriptors(d) {
for (MyDescriptor *d : descriptors) {
d->init(name);
}
}
}
MyHostImpl : public MyHost {
public:
// descriptors must be accessible as members like this
MyDescriptor d_1 = MyDescriptor("abc");
MyDescriptor d_2 = MyDescriptor("123");
MyHostImpl(string n) : MyHost(n, {&d_1, &d_2}) {} // This is the issue
void do_thing_1() {
// UPDATE: This is loose example - but what is important to
// know is that developers need to access / use descriptors
// in methods like this.
d_1.do_thing();
}
}
理想情况下,我想要一种方法来停止明确声明descriptors
项;这是我要消除的{&d_1, &d_2}
。我的团队使用类似的模式,并且由于将向量添加到类中之后不小心不添加到向量的描述符而不断感到沮丧。
答案 0 :(得分:3)
反转ctor语义。让描述符的ctor代替宿主ctor接受描述符指针,而使用宿主引用并将其自身添加到宿主向量中:
MyDescriptor::MyDescriptor(MyDescriptor const&)=delete;
auto& MyDescriptor::operator=(MyDescriptor const&)=delete;
MyDescriptor::MyDescriptor(string n, MyHost& h): name{n},fqn{n+":"+h.get_name()}
{
h.add(this);
};
MyHost::MyHost(string n):name{n}{};
void MyHost::add(MyDescriptor* d){
descriptors.push_back(d);
};
auto& MyHost::get_name()const{
return name;
};
这样,您就不会忘记向主机添加描述符,否则编译器会发出哭声。
MyHostImpl::MyHostImpl(string n):
MyHost{n},
d_1{"abc",*this},/*compiler kills you if you forget this line*/
d_2{"123",*this}/*compiler kills you if you forget this line*/
{};
答案 1 :(得分:0)
是的,至少在C ++ 14中,有一种方法可以直接完成您所要的内容,但是其中涉及许多黑巫毒。在这次Meeting C ++ 2018演讲中:
Better C++14 reflections - Antony Polukhin
Antony解释了如何能够遍历结构的所有成员并访问其类型。他使用它在某些输出流上打印值,但是您可以使用相同的方法将地址推回std::vector<MyDescriptor*>
中。
话虽如此-我认为您应该避免这种模式。只需创建MyDescriptor的向量即可,然后对其进行引用。为什么要使用需要大量扭曲才能产生的指针向量?
答案 2 :(得分:-1)
我不确定您如何想象它会起作用。 C ++没有反射,因此您无法遍历其类成员并检查其类型。所以,对不起,据我所知,这是不可能的。当然,您可以使用一些解决方法,例如直接使用基础基本向量,而不是将两个描述符声明为成员变量(是否有任何需要?),然后隐式地将它们传递给Base构造函数,但是您要做的是重新瞄准是不可能的。
编辑:显然,暗巫术有可能出现,请参考下面的评论。