-1

我有以下功能

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) 类的 init 函数中的行QuadTree工作得很好。

但是,另一个子类 (LinearScheme) 中的这一行*this = LinearScheme()会导致 Seg 错误。

任何想法为什么会发生这种情况?

编辑 还替换该行:

*this = LinearScheme()

有了这个:

*this;

或将其全部删除以消除 Seg Fault ... 为什么?

4

2 回答 2

5

听起来像是不正确的factory method//用法builderdeferred 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以及界面是什么,很难说。

于 2014-03-04T21:29:17.110 回答
2

“...在另一个子类(LinearScheme)中*this = LinearScheme()

“LinearScheme 构造函数为空:LinearScheme::LinearScheme()

如果*this 是LinearMethod 的子类,LinearMethod 的构造函数应该已经被调用,这一行是无用的。除了它调用赋值运算符 - 它是否正确定义?

最好依靠内置的对象构造机制。如果要避免代码重复,请使用 C++11委托构造函数功能。它是专门为消除“init”方法而设计的。

虽然,“如果存在无限递归循环(例如,构造函数 C1 委托给另一个构造函数 C2,而 C2 也委托给 C1),则行为是未定义的。”

因此,避免无限递归取决于您。在您的 QuadTree 中,您可以考虑在构造函数中创建指向 QuadTreeNode 的 nullptr指针

于 2014-03-04T22:27:59.443 回答