我有以下函数
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
构造函数都是递归应用的。QuadTree
类的init函数中的*this = QuadTree(bounds, maxSize)
行工作正常。
然而,另一个子类(LinearScheme)*this = LinearScheme()
中的这一行会导致Seg故障。
你知道为什么会发生这种事吗?
编辑同时替换行:
*this = LinearScheme()
这个:
*this;
或者将其整体移除可以消除Seg故障。。。为什么?
听起来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中的委托构造函数方法。
然而,这两个都不是真正的问题。
它不起作用,因为你可能甚至没有一个有效的*this
来表示尊重。这可能是因为您的使用,也可能是因为创建失败,可能是因为无限递归。
以下是关于该模式的维基百科链接:http://en.wikipedia.org/wiki/Factory_method_pattern
考虑到您所说的必须不断向父类和递归构造传递十几个参数,您可以考虑的一个建议是制作一个小的配置结构,通过引用传递,而不是所有离散参数。这样,您就不必在每次添加/删除另一个参数时不断调整每个签名。
另一个想法是将你的一个对象的构建与知道它们应该如何、在哪里和何时构建并插入你的层次结构的责任完全分开。如果不了解LinearSchme
的实际使用方式以及接口是什么,很难说。
"…在另一个子类中(LinearScheme)*this = LinearScheme()
">
"LinearScheme构造函数为空:LinearScheme::LinearScheme()
">
如果*this是LinearMethod的子类,那么LinearMethod构造函数应该已经被调用了,而这一行是无用的。此外,它调用赋值运算符——它定义正确吗?
最好是依靠内置的构造对象的机制。如果您想避免代码重复,请使用C++11委派构造函数特性。它是专门为消除"init"方法而设计的。
尽管,"如果存在无限递归循环(例如,构造函数C1委托给另一个构造函数C2,C2也委托给C1),则行为是未定义的。">
因此,避免无限递归取决于您。在QuadTree中,您可以考虑在构造函数中创建指向QuadTreeNode的nullptr指针。