初始化const成员并使用父构造函数

时间:2018-01-13 12:38:11

标签: c++ templates constructor initialization

当您继承T并使用using T::T时,有没有办法在模板中初始化const成员?这是一个例子

#include <iostream>
#include <ctime>
#include <string>
#include <memory>

class A {
protected:
  int wake_up_time_;

public:
  A(int wake_up_time): wake_up_time_(wake_up_time) { }

  virtual void hello() const {
    std::cout << "I wake up at " << wake_up_time_;
  }
};

/* B classes inherit from A and have different members some of which vary in  
 * size and type                                                             */
class B1 : public A {
public:
  std::string b;

  B1(int a, std::string b): A(a), b(b) { }
};

class B2 : public A {
public:
  int c;
  double d;

  B2(int a, int c, double d): A(a), c(c), d(d) { }
};

template<class T>
class bird : public T {
  /* this function is more expensive in my case. */
  bool is_early_bird() const { // needs to be const as hello is const
    return this->wake_up_time_ < 6;
  }

  /* would like to have this instead */
  // const bool is_early_bird_;

public:
  /* which we assign in the constructor */
  using T::T;

  void hello() const override { 
    std::cout << (is_early_bird() ? "I am an early bird!" : "Getting up is hard...")
              << std::endl;
  }
};

template<class T>
class cat : public T {
  /* similar comments as in bird class */
  bool is_hunting() const {
    return this->wake_up_time_ < 5 || this->wake_up_time_ > 22;
  }

public:
  using T::T;

  void hello() const override {
    std::cout << (is_hunting() ? "Time to kill stuff" : "Time to sleep")
              << std::endl;
  }
};

int main() {
  std::unique_ptr<A> ptr;
  {
    ptr.reset(new bird<B1>(5, "..."));
    std::cout << "B1 has value " << dynamic_cast<B1*>(ptr.get())->b << std::endl;
  }
  ptr->hello();

  {
    ptr.reset(new cat<B1>(12, "xyz"));
    std::cout << "B1 has value " << dynamic_cast<B1*>(ptr.get())->b << std::endl;
  }
  ptr->hello();

  {
    ptr.reset(new cat<B2>(24, 3, 12.5));
    B2* l_ptr = dynamic_cast<B2*>(ptr.get());
    std::cout << "B2 has value " << l_ptr->c << " and " << l_ptr->d << std::endl;
  }
  ptr->hello();

  {
    ptr.reset(new B2(10, 7, 3.33));
    B2* l_ptr = dynamic_cast<B2*>(ptr.get());
    std::cout << "B2 has value " << l_ptr->c << " and " << l_ptr->d << std::endl;
  }
  ptr->hello();

  return 0;
}

输出

B1 has value ...
I am an early bird!
B1 has value xyz
Time to sleep
B2 has value 3 and 12.5
Time to kill stuff
B2 has value 7 and 3.33
I wake up at 10   

我想要摆脱的是cat::is_huntingbird::is_early_bird中的(在这种情况下是简单的)计算,而是使用const成员。我也有很多函数,它将B1B2类的引用或指针作为参数,因此它似乎不是选择public cat : public Apublic bird : public A类并以2x2继承的B类结束。

1 个答案:

答案 0 :(得分:1)

W.F。在评论部分给出答案。答案是将Model类更改为

cat

template<class T>
class cat : public T {
  const bool is_hunting_ = { this->wake_up_time_ < 5 || this->wake_up_time_ > 22 };

public:
  using T::T;

  void hello() const override {
    std::cout << (is_hunting_ ? "Time to kill stuff" : "Time to sleep")
              << std::endl;
  }
};

这是on this site

所描述的
  

会员初始化
  非静态数据成员可以用两种方式之一初始化:
  ...
  2)通过默认成员初始化程序,它只是成员声明中包含的大括号或等于初始化程序,如果在成员初始化程序列表中省略该成员,则使用该初始化程序。   ...

     

<强>用法
  非静态数据成员或非静态成员函数的名称只能出现在以下三种情况中:
  1)作为类成员访问表达式的一部分,其中类具有此成员或派生自具有此成员的类,包括在非静态成员名称时出现的隐式template<class T> class cat : public T { /* similar comments as in bird class */ bool is_hunting() const { return this->wake_up_time_ < 5 || this->wake_up_time_ > 22; } public: using T::T; void hello() const override { std::cout << (is_hunting() ? "Time to kill stuff" : "Time to sleep") << std::endl; } }; 成员访问表达式用于任何允许这样做的上下文......