У меня есть следующие функции
LinearScheme::LinearScheme() {
cout << " empty constructor" << endl;
}void LinearScheme::init(
int tableId,
std::string &basePath,
std::vector<size_t> &colElemSizes,
TupleDescMap &tupleDescMap,
size_t defaultMaxFragmentSize,
int numCols,
BoundBases &bounds,
std::vector<int> &colsPartitioned )
{
// This linear scheme ignores bounds
// it could be improved to use colsPartitioned for ordering (TODO)
cout << "init Linear Scheme " << endl;
*this = LinearScheme(); //SEGFAULTS HERE
cout << "after cons here?" << endl;
// init private fields
this->tableId_ = tableId;
this->basePath_ = basePath;
this->colElemSizes_ = colElemSizes;
this->numCols_ = numCols;
this->tupleDescMap_ = tupleDescMap;
this->numFragments_ = 0;
this->defaultMaxFragmentSize_ = defaultMaxFragmentSize;
// fragmentSizesFilename_ init
fragmentSizesFilename_ = basePath_ + boost::lexical_cast <string>(tableId_)
+ "_cs";
struct stat st;
// open existing file if exists. Create new otherwise.
if (stat(fragmentSizesFilename_.c_str(), &st) == 0) // file existed
openExisting();
else
createNew();
}
Причина, по которой я инициализирую в init
а не конструктор, потому что LinearScheme
расширяет PartitionScheme
(суперкласс с виртуальными методами) класс и другой класс делают это, где конструктор используется рекурсивно.
у меня есть QuadTree
класс, который делает ту же инициализацию, потому что каждый QuadTree
Конструктор применяется рекурсивно. *this = QuadTree(bounds, maxSize)
строка в функции инициализации QuadTree
класс работает просто отлично.
однако эта строка в другом подклассе (LinearScheme) *this = LinearScheme()
вызвать ошибку сегмента.
Есть идеи, почему это может произойти?
РЕДАКТИРОВАТЬ
Также замена строки:
*this = LinearScheme()
с этим:
*this;
или удаление его в целом избавляет от неисправности сега … почему?
«… в другом подклассе (LinearScheme) *this = LinearScheme()
«
«Конструктор LinearScheme пуст: LinearScheme::LinearScheme()
«
если * это подкласс LinearMethod, конструктор LinearMethod уже должен был быть вызван, и эта строка бесполезна. Кроме того, он вызывает оператор присваивания — правильно ли он определен?
Лучше полагаться на встроенный механизм конструирования объектов. Если вы хотите избежать повторения кода, используйте C ++ 11 делегирующие конструкторы особенность. Он был специально разработан для устранения методов «init».
Хотя, «если существует бесконечно рекурсивный цикл (например, конструктор C1 делегирует другому конструктору C2, а C2 также делегирует C1), поведение не определено».
Так что это зависит от вас, чтобы избежать бесконечной рекурсии. В вашем QuadTree вы можете рассмотреть возможность создания nullptr указатели QuadTreeNode в конструкторе.
Похоже, неправильно factory method
/ builder
/ deferred construction
использование. Для многих из этих шаблонов создания объектов функция, которая создает ваши объекты, должна быть статическим методом, потому что еще не существует экземпляра для манипулирования. В других вы потенциально можете манипулировать уже созданным экземпляром. В любом случае, если вы на самом деле создаете объект типа класса внутри функции, вы должны использовать new и в конечном итоге вернуть его.
Если вы вместо этого собираетесь на helper
метод, чтобы помочь с инициализацией, тогда вы просто не должны создавать объект в самом методе, и вы должны просто инициализировать его части в вашем помощнике.
Пример фабричного образца:
LinearScheme* LinearScheme::create(...all_your_args....) {
/* construct the thing we are building only if it
* pass any arguments into him that he can handle directly if you'd like
*/
LinearScheme *out = new LinearScheme(...);
/* do whatever else you have to do */
....
return out;
}
или это helper
виды, которые вы, кажется, хотите
/* this time let's just do 'init' on your object */
void LinearScheme::init(....args....) {
/* possibly check if init has been done already */
if ( this->init ) return;
/* proceed to do your initialization stuff
* but don't construct the 'this' instance since it should already exist
*/
this->init = true; //so we don't init again if you don't need multiple init's
}
В качестве альтернативы вы можете рассмотреть методы конструктора делегата в C ++ 11 alex.
Однако ни один из них действительно не кажется мне актуальной проблемой.
Это не работает, потому что либо у вас, вероятно, даже нет действительного *this
к почтению. Это может быть связано с вашим использованием или с тем, что не удалось создать потенциально из-за бесконечной рекурсии.
Вот ссылка на шаблон википедии: http://en.wikipedia.org/wiki/Factory_method_pattern
Учитывая то, что вы сказали о необходимости передавать дюжину аргументов как родительским классам, так и вашей рекурсивной конструкции, вы можете рассмотреть одно предложение — создать небольшую конфигурационную структуру, которую вы передаете по ссылке, а не по всем дискретным параметрам. Таким образом, вам не нужно постоянно корректировать каждую сигнатуру при каждом добавлении / удалении другого параметра.
Другая идея состоит в том, чтобы полностью отделить конструкцию одного из ваших объектов от ответственности знания того, как, где и когда они должны быть созданы и вставлены в вашу иерархию. Трудно сказать, не понимая, как вы будете на самом деле использовать LinearSchme
и что это за интерфейс.