Я пытаюсь найти эффективный способ (используя полиморфизм) для копирования определенных атрибутов между двумя производными классами извне. У меня есть набор классов данных, которые являются производными от базового класса DataClassA
, Я хочу работать с этими классами данных в отдельном классе фильтра, который принимает DataClassA
ссылки в качестве входных и выходных параметров. Фильтр выполнит необходимые операции, общие для DataClassA
, но я также хочу распространять специфичные для класса атрибуты из моего ввода в выходной класс. Рассматривать:
class DataClassA
{
public:
virtual void copyAttributes( DataClassA& copyFrom );
}
class DataClassB : public DataClassA
{
public:
virtual void copyAttributes( DataClassA& copyFrom );
};
class DataFilter
{
void run( DataClassA& input, DataClassB& output )
{
//do some calculations here
...
//then copy over attributes
output.copyAttributes( input );
}
};
Моя проблема, очевидно, в том, что copyAttributes()
зависит от необходимости знать типы входных и выходных производных классов (которые не обязательно должны быть одинаковыми). Однако фильтр будет обрабатывать только ссылки на базовый класс. DataClassA
, Мой рефлекс просто установить dynamic_cast
хотя я рискую получить пощечину (и другие возможные негативные последствия). Если бы я сделал это, я бы просто создал copyAttributes
метод для каждого производного класса, который называется copyAttributes
родительского класса, а затем использовать dynamic_cast
чтобы увидеть, если copyFrom
Объект того же типа:
void DataClassB::copyAttributes( DataClassA& copyFrom )
{
//copy attributes from parent class
DataClassA::copyAttributes( copyFrom );
//test if the class being copied from is of type DataClassB
DataClassB* copyPtr = dynamic_cast<DataClassB*>©From;
if( copyPtr != NULL )
{
//copy DataClassB-specific attributes from copyFrom to this
...
}
}
Наиболее похожий пост, который я смог найти по этой проблеме, был здесь Виртуальные функции и полиморфизм. Мои основные вопросы: 1) не подходит ли мое предполагаемое использование dynamic_cast ?; и 2) если так, как я мог бы реализовать это copyAttributes
по-другому? Были ссылки на использование шаблона дизайна посетителя, хотя я не уверен, как это будет выглядеть.
Это своего рода более простая версия того, что делает Visualization Toolkit (VTK) в том смысле, что я использую классы фильтров, которые работают с рядом различных классов данных. Интересно, что они обрабатывают RTTI, включая макросы, которые включают в себя строковое имя классов и родительские классы, которые можно сравнивать напрямую для правильного уменьшения типов данных.
Кажется, вы хотите multi-dispatch (как это я сделал здесь: https://ideone.com/8VxALs)
Это требует, чтобы посетитель знал каждый производные типы.
Другой подход заключается в использовании dynamic_cast
каждый раз.
Простая двойная отправка может быть сделана следующим образом:
class DataClassA
{
public:
virtual ~A() {}
virtual void copyAttributes(DataClassA& copyFrom) { copyFrom.copyAttributesToA(*this); }
virtual void copyAttributesToA(DataClassA& copyTo) { /* Implementation to copy A -> A */ }
virtual void copyAttributesToB(DataClassB& copyTo) { /* Implementation to copy A -> B */ }
};
class DataClassB : public DataClassA
{
public:
void copyAttributes(DataClassA& copyFrom) override { copyFrom.copyAttributesToB(*this); }
void copyAttributesToA(DataClassA& copyTo) override { /* Implementation to copy B -> A */ }
void copyAttributesToB(DataClassB& copyTo) override { /* Implementation to copy B -> B */ }
};