Конструктор не вызывается ожидаемое количество раз

Вот код, который вызывает проблему:

class Base
{
public:
virtual void fun()
{
cout<<"Base";
}
};
class Der:public Base
{
Base &pb;
public:
Der(Base&b):pb(b){}
virtual void fun()
{
cout<<"Der...";
pb.fun();
}
};
int main()
{
Der(Der(Base())).fun();
return 0;
}

Запустите этот код, и в результате появится «Der … Base …»! Это так удивительно, я не могу понять, почему результат не «Der … Der … Base», что логически правильно ?!
Затем я заменяю член в классе Der Base&pb с Base*pb и измените код на легальный, в конце концов, вывод будет правильным: «Der … Der … Base»!
Я отлаживаю код и нахожу, что когда я использую Base&pb, конструктор Der запускается только один раз при использовании Base*pb, конструктор бежал дважды правильно!
Любой, кто может объяснить мне, что случилось и почему?

0

Решение

В Der(Der(Base())).fun() выражение внутреннего Der(Base()) дает rvalue — компилятор оптимизирует код с помощью копия elision и удаляет ненужное копирование объектов.

1

Другие решения

В дополнение к ответу @ icepack и последующему обсуждению в комментариях (резюме: код Der(der) является приведением, которое может быть или не быть реализовано с использованием конструктора; в вашем случае это не так), обходной путь для вас: вы должны четко заявить о своем намерении, не используя конструктор.

Я бы переписал ваш код примерно так:

class Base
{
public:
virtual void fun()
{
cout<<"Base";
}
};

class Der:public Base
{
Base &pb;
Der(Base& b) : pb(b) {}
public:
static Der Decorate(Base&& b){ return Der(b); }
virtual void fun()
{
cout<<"Der...";
pb.fun();
}
};

int main()
{
Der::Decorate(Der::Decorate(Base())).fun();
return 0;
}

(выходы: Der … Der … Base).


Изменение кода для принятия указателя это просто:

class Base
{
public:
virtual void fun()
{
cout << "Base";
}
};

class Der : public Base
{
Base* pb;
Der(Base* b) : pb(b) {}
public:
static Der Decorate(Base* b){ return Der(b); }
virtual void fun()
{
cout << "Der...";
pb->fun();
}
};

int main()
{
Der::Decorate(&Der::Decorate(&Base())).fun();
return 0;
}
0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector