質問

Gotw 80 includes the following example:

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

The article goes to discuss why the line s = f() is incorrect - due to object lifetimes and order of construction. The article states that at the time, the error wasn't picked up by the compiler.

However, ignoring the problems of order of intialisation and object lifetime, I don't see how s = f() in the parameter list of the constructor can be legal syntactically - it appears to be trying to initialise a member in the parameter list (or perhaps declaring a default value). Can anyone explain what this syntax is trying to do?

役に立ちましたか?

解決

Syntactically it's legal... when you have a base class with a constructor that takes arguments you can of course pass any expression as parameter:

strut A {
    A(int) {}
};

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

The problem is that when evaluating the expression in the example the object is not even yet a fully constructed A instance, so that code is invalid for two distinct reasons:

  1. Calls a method of A of an non-instance (the constructor didn't start yet): f() call is illegal.
  2. Assigns to a member that hasn't been initialized: s=... is illegal.

他のヒント

It looks like the intention was to call f() and assign the result to B::s. Afterward, the result of that assignment (which is s) would be used as actual parameter when calling the inherited A constructor.

It's syntactically valid. Replace s in that expression with some non-member variable, and g++ accepts it without issue. You might see similar syntax used more often with ordinary function calls instead of constructor calls.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top