【问题标题】:Initialize const member and use parent constructor初始化 const 成员并使用父构造函数
【发布时间】:2018-01-13 12:38:11
【问题描述】:

当你继承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 类结束似乎不是一个选项。

【问题讨论】:

  • 是什么阻止了你?尝试时遇到什么错误?没有更简单的代码可以重现吗?
  • @W.F. 没有更简单的代码可以重现吗?我想强调我有多个类,如 B1B2 以及多个类,如 catbird 以避免我使用的 cmets例如,可以让 cat 继承自 A。此外,我还想强调 B1B2 在构造函数参数的数量及其类型方面有所不同。
  • @W.F. 是什么阻止了你?尝试时遇到什么错误? 如何使用 using T::Tconst bool is_early_bird_ 成员初始化类 bird 而没有 bird::is_early_bird 函数?
  • aaam...[this]?
  • 我敢打赌它是 c++11。很高兴它有帮助。

标签: c++ templates constructor initialization


【解决方案1】:

W.F.在评论区给出答案。答案是将 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;
  }
};

来自

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;
  }
};

这被描述为on this site

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

用法
非静态数据成员或非静态成员函数的名称只能出现在以下三种情况:
1) 作为类成员访问表达式的一部分,其中类要么具有此成员,要么派生自具有此成员的类,包括使用非静态成员名称时出现的隐式 this-&gt; 成员访问表达式在任何允许这样做的情况下......

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-10
    • 2021-09-04
    • 2021-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多