2014-09-17 2 views
0

Я хочу сделать эквивалент следующее для инициализации элемента данных my_abc (который я подозреваю, не будет работать):Как инициализировать, во время строительства, абстрактный элемент данных базового класса из производного экземпляра класса

class ABC { // abstract base class 
public: 
    virtual ~ABC {}; 
} 

class SomeClass { 
public: 
    SomeClass(ABC& abc); // argument will actually be instance of derived class 
private: 
    ABC my_abc; // needs to be set from constructor argument 
} 

SomeClass::SomeClass(ABC& abc) : my_abc(abc) 
{...} // copy construct `my_abc` from argument 

Я подозреваю, что это не сработает, если производный класс ABC передан конструктору SomeClass, потому что конструктор копирования производного класса не будет вызываться для инициализации члена my_abc.

Правильно ли я? Если да, что мне делать?

+5

Если 'ABC' действительно абстрактный, вы не можете иметь экземпляр-член' ABC my_abc; '. Что вы можете сделать, это использовать ссылку: 'ABC & my_abc;'. Если ваша копия не перейдет на простое 'ABC', это называется _splicing_. –

+0

@ πάνταῥεῖ довольно уверен, что вы имели в виду [* нарезка *] (http://stackoverflow.com/questions/274626/what-is-the-slicing-problem-in-c) (разделить), а не * сращивание * (до собрать). = P – WhozCraig

+0

@WhozCraig Ooops, да! _slicing_, конечно. –

ответ

4

Вы сказали,

SomeClass(ABC& abc); // argument will actually be instance of derived class

, а затем, у вас есть данные член

ABC my_abc; 

При инициализации my_abc с помощью abc, вы получите объект базового класса, не фиксирует часть производного класса. Оформить вопрос object slicing. Это то, чего вы надеетесь достичь? Думаю, нет.

Как указано в комментарии от πάντα ῥεῖ, вы должны сохранить ссылку на базовый класс.

ABC& my_abc_ref; 

Затем

SomeClass::SomeClass(ABC& abc) : my_abc_ref(abc) {...} 

не должно быть проблемой.

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

class ABC { 
public: 
    virtual ~ABC() {} 
    virtual ABC* clone() const = 0; 
}; 

#include <memory> 

class SomeClass { 
public: 
    SomeClass(ABC& abc); 
private: 
    std::unique_ptr<ABC> my_abc; 
}; 

SomeClass::SomeClass(ABC& abc) : my_abc(abc.clone()) {} 

Это просто показывает механизм. Чтобы создать код качества продукции, вы должны принять политические решения о поведении копирующих и перемещающих конструкторов, а также скопировать и переместить операторы присваивания SomeClass и реализовать их соответствующим образом.

PS

Класс ABC, как размещены, не является абстрактным базовым классом. Он не имеет никаких чистых виртуальных функций.

+0

Возможно, упоминание о том, что 'ABC', очевидно, не имеет никаких эллиптических дополнительных чисто виртуальных функций-членов и, следовательно, не является абстрактным ... – Deduplicator

+0

Если это действительно абстрактно, возможно, используйте' ABC * 'вместо' ABC & ', используйте какой-то вид функции «клонировать», а не конструктор копирования, и уничтожить 'my_abc' в' ~ SomeClass() '. –

Смежные вопросы