У меня есть дьявол понимания времени. Рассмотрим следующий код:
class Animal
{
public:
virtual void makeSound() {cout << "rawr" << endl;}
};
class Dog : public Animal
{
public:
virtual void makeSound() {cout << "bark" << endl;}
};
Animal* pFunc()
{
return new Dog();
}
Animal& rFunc()
{
return *(new Dog());
}
Animal vFunc()
{
return Dog();
}
int main()
{
Animal* p = pFunc();
p->makeSound();
Animal& r1 = rFunc();
r1.makeSound();
Animal r2 = rFunc();
r2.makeSound();
Animal v = vFunc();
v.makeSound();
}
И результаты: "bark bark rawr rawr".
В Java-мышлении (который, по-видимому, испортил мою концептуализацию С++), результатом будет "кора коры коры". Я понимаю из своего предыдущего вопроса, что это различие связано с нарезкой, и теперь я хорошо понимаю, что такое резка.
Но скажем, что мне нужна функция, возвращающая значение Animal, которое действительно является Собакой.
- Правильно ли я понимаю, что самое близкое, что я могу получить, это ссылка?
- Кроме того, он должен использовать тот, который использует интерфейс rFunc, чтобы увидеть, что возвращаемая ссылка назначает Animal &? (Или иначе преднамеренно назначить ссылку на Животное, которое посредством нарезки отбрасывает полиморфизм.)
- Как я должен возвращать ссылку на вновь созданный объект, не делая глупую вещь, которую я сделал выше в rFunc? (По крайней мере, я слышал, что это глупо.)
Обновление: поскольку все, кажется, до сих пор согласны с тем, что rFunc это незаконно, что вызывает другие связанные вопросы:
Если я передам указатель, как мне сообщить программисту, что указатель не их удалить, если это так? Или, в качестве альтернативы, как мне сообщить, что указатель может быть удален в любое время (из того же потока, но с другой функцией), чтобы вызывающая функция не сохраняла его, если это так. Это единственный способ сообщить это через комментарии? Это кажется неаккуратным.
Примечание. Все это приводит к идее шаблонной концепции shared_pimpl, над которой я работал. Надеюсь, я узнаю достаточно, чтобы опубликовать что-то об этом через пару дней.