Применяется ли полиморфизм к ценностям?Или используя конструктор перемещения производного класса при возврате по (base-) значению - PullRequest
1 голос
/ 14 апреля 2019

Я создаю какой-то фабричный метод, который возвращает DerivedClass как BaseClass следующим образом:

BaseClass Factory() 
{
    return DerivedClass();
}

Прав ли я, что конструктор перемещения BaseClass используется, когда я вызываю этот метод:

BaseClass object = Factory();

Поскольку я не могу сделать конструктор перемещения из BaseClass virtual, есть ли другой способ заставить конструктор перемещения из DerivedClass быть взятым?

Edit1: дополнительная информация - я уже думал о указателях. Но дело в том, что я хочу экспортировать фабричную функцию в DLL, и я хотел сделать ее максимально простой для пользователя. Стандартные указатели могут привести к утечке памяти, и, с другой стороны, не все знакомы с умными указателями.

Edit2: Насколько я понял, реальный вопрос был: работает ли полиморфизм и с возвратом по значению?
И ответ НЕТ.

Ответы [ 3 ]

5 голосов
/ 14 апреля 2019

Я думаю, что вы не должны делать:

BaseClass Factory() 

А точнее

// You'll need to delete
BaseClass* Factory() {
    return new Derived();
}

// You will not need to delete
unique_ptr<BaseClass> Factory() {
    // return new Derived();
    // As the comments point out: prefer use of make_unique
    return std::make_unique<Derived>();
}

В противном случае вы нарезаете ваш объект.

Полиморфизм работает только в указателях и ссылках .

2 голосов
/ 14 апреля 2019

В C ++ вы не возвращаете производный объект как объект базового класса.Это похоже на ac # way.Вы должны использовать указатели.

Я предполагаю, что это то, что вы хотите.

BaseClass* Factory() 
{
    return new DerivedClass();
}

Кроме того, я никогда не слышал о понятии 'конструктор перемещения'.

1 голос
/ 14 апреля 2019

Обычная переменная, поле, тип возвращаемого значения и т. Д. Базового класса в C ++ не могут содержать значения подкласса.Это отличается от других объектно-ориентированных языков, таких как Java, и связано с тем, как объекты фактически представляются в памяти - для хранения полиморфного значения требуется указатель или ссылка.(В Java и аналогичных языках все переменные, содержащие объекты, на самом деле являются указателями на объект, который сам хранится в другом месте, поэтому детали реализации скрыты от программиста.)

Решение состоит в том, чтобы использовать указатель, чтобыВы используете полиморфизм.Наивной версией этого является возвращение функции BaseClass * и изменение выражения возврата на new DerivedClass(), однако это позволяет легко открывать ошибки утечки памяти, поскольку необходимо вручную убедиться, что вызывающий объект уничтожен прион больше не нужен (через оператора delete).Предпочтительным решением является использование std::shared_ptr<BaseClass> или std::unique<BaseClass> в качестве возвращаемого типа, что обеспечит уничтожение объекта, когда ссылка на него больше не существует.

...