Синтаксис 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
Например, этот код является недействительным по двум причинам:
- Вызывает метод
A
неэкземпляра (конструктор еще не запущен):f()
Звонок незаконен. - Назначает члену, который не был инициализирован:
s=...
незаконно
Похоже, что намерение было позвонить f()
и присвоить результат B::s
, Впоследствии, результат этого назначения (который s
) будет использоваться в качестве фактического параметра при вызове унаследованного A
конструктор.
Это синтаксически верно. замещать s
в этом выражении с некоторой переменной, не являющейся членом, и g++ принимает это без проблем. Вы можете увидеть похожий синтаксис, который чаще используется с обычными вызовами функций вместо вызовов конструктора.