【问题标题】:c++ derived class needs to tweak base class via callbackc++派生类需要通过回调调整基类
【发布时间】:2021-05-23 07:37:19
【问题描述】:

我想创建一个基类 class==> 派生类设置,其中基类的构造函数有一个回调来运行(可能很复杂)函数,以使用派生类的信息修改基类的私有成员。但是,我遇到了先有鸡还是先有蛋的问题,因为基类构造函数派生类的成员初始化之前运行。下面是演示问题的代码:

#include <iostream>
#include <functional>

class B
{
  public:
    typedef std::function<void(std::string &)> mod_func_t;

    B(const mod_func_t &m) : foo("base str")
    {   
      std::cout << "Base constructor\n";
      m(foo);
      std::cout << "base constructor finally has: " << foo << std::endl;
    }   

  private:
    std::string foo;
};

class D : public B
{
  public:
    D(const std::string &input) :
      B(std::bind(&D::my_f, this, std::placeholders::_1)),
      input_(input)
    {   
      std::cout << "Derived constructor\n";
    }   

  private:
    void my_f(std::string &s) 
    {   
      std::cout << "Derived class' modification function\n";
      s += input_; // <== Crashes here because input_ is not yet constructed
    }   

    const std::string input_;
};

int main()
{
  D d("my input");
  return 0;
}

这样做的正确方法是什么?

【问题讨论】:

    标签: c++ oop derived-class


    【解决方案1】:

    一种方法是让D在调用B的构造函数之前计算调整后的string

    class D : public B {
      D(std::string str)
       : B(my_f(str))
      {}
    
      std::string my_f(std::string str) { return str + "..."; }
    };
    

    第二种方法是让构造函数 D 的主体做一些工作。这里adjust_base也可以是virtual

    class D : public B {
      D(std::string str)
       : B(str)
      {
         adjust_base();
      }
    
      void adjust_base();
    };
    

    【讨论】:

      【解决方案2】:

      我相信 CRTP 可以帮助您解决这个问题。 有一个简单的例子:

      #include <iostream>
      #include <functional>
      
      template <typename Derived>
      class B
      {
        public:
       
          B() : foo("base str")
          {   
            static_cast<Derived*>(this)->m(foo);
            std::cout << "Base constructor\n";
            std::cout << "base constructor finally has: " << foo << std::endl;
          }
          
          void m(std::string& str) { //... }   
      
        private:
          std::string foo;
          friend Derived;
      };
      
      class D : public B<D>
      {
        public:
          D(std::string &input) :
            B(),
            input_(input)
          {   
            std::cout << "Derived constructor\n";
          }   
          void m(const std::string& str) { //... }
      
        private:
          void my_f(std::string &s) 
          {   
            std::cout << "Derived class' modification function\n";
            s += input_; // <== Crashes here because input_ is not yet constructed
          }   
      
          const std::string input_;
      };
      
      int main()
      {
        D d("my input");
        return 0;
      }
      

      【讨论】:

      • 未定义行为:static_cast&lt;Derived*&gt;(this)-&gt;m(foo);。在B() 中尚不存在D 对象。
      猜你喜欢
      • 2016-07-11
      • 2016-10-06
      • 2010-12-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-08
      相关资源
      最近更新 更多