有没有一种方法可以将对C ++类成员的引用添加到向量中而无需显式添加它们?

时间:2019-03-10 12:44:38

标签: c++ class composition

我正在尝试确定可以使用哪种模式以更“组合”的方式和更少“命令式”的方式声明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}。我的团队使用类似的模式,并且由于将向量添加到类中之后不小心不添加到向量的描述符而不断感到沮丧。

3 个答案:

答案 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构造函数,但是您要做的是重新瞄准是不可能的。

编辑:显然,暗巫术有可能出现,请参考下面的评论。