Как я понимаю временные, следующий код должен работать, но это не так.
struct base
{
virtual~base() {}
virtual void virt()const=0;
};
struct derived:public base
{
virtual void virt()const {}
};
const base& foo() {return derived();}
int main()
{
foo().virt();
return 0;
}
Вызов virt () дает ошибку «чисто виртуальная функция называется». Почему это так, и что мне делать?
Кажется, вы ожидаете const
ссылка на продление срока службы временного. Есть определенные ситуации, когда этого не происходит. Одна из таких ситуаций при возврате временного:
Второй контекст [в котором временные объекты уничтожаются в точке, отличной от конца полного выражения], — это когда ссылка связана с временным объектом. Временный объект, к которому привязана ссылка, или временный объект, являющийся полным объектом подобъекта, к которому привязана ссылка, сохраняется в течение всего времени существования ссылки, за исключением:
[…]
- Время жизни временной привязки к возвращенному значению в операторе возврата функции (6.6.3) не продлевается; временное уничтожается в конце полного выражения в операторе возврата.
Поскольку вызов функции-члена объекта возвращается foo()
потребуется преобразование lvalue-в-значение, и объект недопустим (не получен из типа base
), вы получите неопределенное поведение:
Если объект, на который ссылается glvalue, не является объектом типа
T
и не является объектом типа, полученного изT
или, если объект не инициализирован, программа, которая требует этого преобразования, имеет неопределенное поведение.
Вы возвращаете ссылку на временный, который разрушен когда функция заканчивается в конце return
заявление, и вы получите неопределенное поведение.
Вы не можете вернуть какую-либо ссылку на временный и если вы возвращаете base
по значению вы получите нарезку, поэтому, если вы действительно хотите, чтобы это работало, вы должны вернуть std::unique_ptr<base>
,
Я не думаю, что вы можете вернуть ссылки на подобные объекты. Экземпляр производного () выходит из области видимости, как только возвращается функция foo (). Есть
base *foo() { return new derived(); }
а также
foo()->virt();
должно сработать.
Во время звонка объекта нет, локальный объект удален. Там не будет Vtable для просмотра. Пытаться:
base& foo() { return *new derived(); }
Ваш временный объект производного () расположен в стеке. Это может быть как-то связано с повышением качества объекта.
постоянная база& foo () {производная * d = новая производная (); возврат * d; }
Работает просто отлично, для меня.
Измените часть проблемы на это:
class A {
public:
const base &foo() { return d; }
private:
derived d;
};
Таким образом, время жизни производного объекта равно времени жизни А, и проблем не будет.