Нарезка на унаследованные объекты

Следующие случаи указывают на проблему срезов: во время назначения: /questions/31014972/chto-takoe-narezka-obektov/31014975#31014975

Во время вызова функции: что такое нарезка объектов?

Мой вопрос заключается в том, не могут ли быть решены оба этих случая, если оператор присваивания и конструктор копирования объявлены виртуальными, а производный класс соответствующим образом скопирует необходимые данные? Если это так, то в принципе передача по значению все еще должна работать в этих случаях, верно?

2 ответа

Решение

Очевидно, вы не можете объявить конструкцию копии virtual: Объекта пока нет. Вы можете отключить конструкцию копирования, хотя.

Тем не менее, делая назначение virtual все еще не работает, потому что при нарезке объектов статический тип назначенного объекта все еще является просто базовым классом. Он никогда не станет производным классом, независимо от того, какой тип вы ему назначаете.

Нет. Аргумент передается по значению, и поэтому создается новый базовый объект.

Виртуального конструктора не существует, так как virtual означает "зависит от динамического типа this", и до запуска конструктора объект даже не существует, поэтому он не может иметь производный динамический тип.

Виртуальные операторы присваивания также не помогли бы, так как они зависели бы от типа объекта, которому присваиваются, а не от типа объекта, которому присваиваются.

Если вы хотите иметь возможность копировать по значению, но при этом иметь полиморфное поведение, вы можете создать объект, который содержит указатель на другой объект и который клонирует объект в его конструкторах и операторах присваивания (используя что-то вроде value_ptr из Wheels Martinho Fernandes' Wheels библиотека):

class Base {
    public:
    virtual Base* clone() const = 0;
    virtual void do_stuff() = 0;
};

class CopyablePolymorphic {
public:
    CopyablePolymorphic(Base* base) : ptr(base) {}
private:
    value_ptr<Base> ptr;
};

class Derived1 : public Base {
public:
    virtual Base* clone() const {
        return new Derived1(*this);
    }
    virtual void do_stuff() {
        //Derived1 stuff
    }
};

class Derived2 : public Base {
public:
    virtual Base* clone() const {
        return new Derived2(*this);
    }
    virtual void do_stuff() {
        //Derived2 stuff
    }
};

//etc...
Другие вопросы по тегам