Синтаксис getw 80 - инициализация в списке параметров

Gotw 80 включает в себя следующий пример:

  // Example 1
  //
  #include <string>
  using namespace std;

  class A
  {
  public:
    A( const string& s ) { /* ... */ }
    string f() { return "hello, world"; }
  };

  class B : public A
  {
  public:
    B() : A( s = f() ) {}
  private:
    string s;
  };

  int main()
  {
    B b;
  }

В статье рассказывается, почему линия s = f() неверно - из-за времени жизни объекта и порядка строительства. В статье говорится, что в то время ошибка не была обнаружена компилятором.

Однако, игнорируя проблемы порядка инициализации и времени жизни объекта, я не вижу, как s = f() в списке параметров конструктор может быть синтаксически допустимым - он пытается инициализировать элемент в списке параметров (или, возможно, объявить значение по умолчанию). Кто-нибудь может объяснить, что пытается сделать этот синтаксис?

2 ответа

Решение

Синтаксически это допустимо... когда у вас есть базовый класс с конструктором, который принимает аргументы, вы, конечно, можете передать любое выражение в качестве параметра:

strut A {
    A(int) {}
};

struct B : A {
    B() : A( any expression that returns an int ) {}
};

Проблема в том, что при оценке выражения в примере объект даже не является полностью сконструированным A Например, этот код является недействительным по двум причинам:

  1. Вызывает метод A неэкземпляра (конструктор еще не запущен): f() Звонок незаконен.
  2. Назначает члену, который не был инициализирован: s=... незаконно

Похоже, что намерение было позвонить f() и присвоить результат B::s, Впоследствии, результат этого назначения (который s) будет использоваться в качестве фактического параметра при вызове унаследованного A конструктор.

Это синтаксически верно. замещать s в этом выражении с некоторой переменной, не являющейся членом, и g++ принимает это без проблем. Вы можете увидеть похожий синтаксис, который чаще используется с обычными вызовами функций вместо вызовов конструктора.

Другие вопросы по тегам