构造函数的C ++语法“'Object1 a(1,Object1(2))''

时间:2010-03-27 05:04:55

标签: c++ syntax

我在程序

中有这样的语法
/* The Object1 is allowed to be changed */
class Object1 : BaseClass {
    BaseClass *link;
    int i;
    public: 
    Object1(int a){i=a;}
    Object1(int a, Object1 /*place1*/ o) {i=a; link= &o;}
};

int main(){
/* The initialization syntax must be preserved. No any new(), no other local objects b,c */
    Object1 a(1, /*place2*/ Object1(2));
    ...
}

我需要在place1中做什么?我想保存第一个对象中第二个对象的链接(指针)。我应该使用place1参考“&”吗?

什么类型的地方有“Object1(2)”?它是匿名对象的构造函数吗?它会有“自动”存储类型吗?

由于

更新:

在place2中,语法是固定的,我真的必须支持创建“链”,比如

    Object1 a(1, Object1(2, Object1(6, Object1(999753))));

我不能在a。的定义中添加任何符号。

UPDATE2:  for place1:Object1(int a, Object1 &o) {i=a; link= &o;}Object1 a(1, Object1(2)); in place2我有编译错误(g ++):

main.cpp||In function `int main()':|
main.cpp|19|error: no matching function for call to `Object1::Object1(int, Object1)'|
main.cpp|9|note: candidates are: Object1::Object1(const Object1&)|
main.cpp|14|note:                 Object1::Object1(int, Object1&)|
main.cpp|13|note:                 Object1::Object1(int)|

6 个答案:

答案 0 :(得分:4)

在“place1”中,您需要一个参考。 Object1未完全定义,因此您无法按值获取它。那就是说,你不想通过价值;当你获取它的地址时,你将获得副本的地址,而不是实际的对象。

由于您只需要指向BaseClass的指针,因此仅对该参数设置该限制可能更有意义。 (当然,如果您确实需要Object1,请在linkObject1* link;类型中反映出来。

还要考虑使用初始化列表:

Object1(int a) : i(a), link(0) /* <- important! */ { }
Object1(int a, BaseClass& o) : i(a), link(&o) { }

始终使用初始化列表。

“place2”使用构造函数创建一个未命名的Object1实例。它有无存储(?) auto存储空间和dies at the end of the expression

也就是说,一旦你在Object1 a(1, /*place2*/ Object1(2));中击中了分号,它就不再存在了,你有一个指向不存在的对象的指针!这会导致未定义的行为。

给它一个超出表达式的生命周期:

Object1 x(2);    
Object1 a(1, x);

始终确保在引用某个对象时,它会在您引用它的整个时间内生效。


您的新编译错误是因为您无法引用临时变量。但可以使用const-reference。问题是,你的指针现在需要指向const BaseClass,这可能会削弱你想要的东西。

不幸的是,您的设计需要重新加工。

答案 1 :(得分:2)

放置1:在此处使用指针(*)代替引用(&amp;)。指针语法更明确地表示链接。

地点2:这里将创建所谓的“临时”对象。是的,它将涉及对Object1的构造函数的调用。此外,是的,存储将是“自动”,因为它将在堆栈上创建。

但是,要小心。临时将在您在构造函数中引用它之前死掉。这肯定会使你的程序崩溃。

如果必须传递临时值,则可以通过在堆上创建副本来成功。像这样:

class Object1
{
    BaseClass* link;
    int i;
    Object1(int a) : i(a), link(NULL) {}
    Object1(int a, const Object1& o) : i(a), link(new new Object1(o)) {} 
    Object1(const Object1& other) i(other.i) link(other.link) {} //Copy constructor
    virtual ~Object1() { delete link; } //Don't forget the 'delete' in destructor.
};

然后在你的主要你可以()这样做:

int main() 
{
    Object1 a(3, Object1(2));
    ....
}

请注意Object1类中的析构函数。确保在其中的链接上调用delete operator。然而,这样的呼叫会导致所有孩子被删除。如果这不是您想要的,请相应地更改删除机制。无论如何,别忘了删除。

另外,确保析构函数是虚拟的。那是因为你将在指向派生类对象的基类指针上调用delete。

答案 2 :(得分:0)

您不能在声明中使用Object1的实例(它尚未声明)。您可以在类声明之前添加一个称为前向声明的内容,如下所示:

// Forward declaration
class Object1;

// Now the class body
class Object1 {
    // some reference to Object1 here
};

但是,我仍然不完全清楚你要对这段代码做什么。有关您希望此构造函数执行的操作的更多信息可能会有所帮助?我怀疑你可能想要使用指针或传递引用,而不是传值。

答案 3 :(得分:0)

构造函数参数o是您传入的Object1实例的副本(因为它是按值传递 。在您的构造函数中,当您将成员指针设置为其地址时,该地址就是堆栈帧,在构造函数返回后它将无效。

这是另一种方法(当然还有其他方法):

class Object1 : BaseClass
{
    BaseClass *link;
    int i;

public: 
    // - Prefer initialization to assignment
    // - Initialize ALL of your members
    Object1(int a) : link(NULL), i(a) {}

    // This instance assumes ownership of p
    Object1(int a, Object1 *p) : link(p), i(a) {}

    ~Object1() { delete link; }
};

int main()
{
    Object1 a(1, new Object1(2));
    ...
}
编辑:嗯,我能看到你使用链式设计的唯一方法就是这样的丑陋:

class Object1 : BaseClass
{
    BaseClass *link;
    int i;

public:
    Object1(int a) : link(NULL), i(a) {}

    Object1(int a, const Object1& o) : link(new Object1(o)), i(a) {}

    // Copy constructor
    Object1(const Object1& other) : link(NULL), i(other.a)
    {
        // Deep copy linked object
        if (other.link != NULL)
        {
            link = new Object1(*other.link);
        }
    }

    // Assignment operator that does deep copy
    const Object1& operator=(const Object1& that)
    {
        // Check for assignment to self
        if (this != &that)
        {
            delete this.link; 
            this.link = NULL;

            // Deep copy linked object
            if (that.link != NULL)
            {
                this.link = new Object1(*that.link);
            }

            this.i = that.i;
        }
    }

    ~Object1() { delete link; }
};

int main()
{
    Object1 a(1, new Object1(2));
    ...
}

答案 4 :(得分:0)

你写的不可能做你想做的事。 Object1 /*place2*/的生命周期在构造函数之后结束,因此您将拥有一个悬空指针。

一般情况下,您希望Object1 /*place2*/成为引用或直接指针[在这种情况下,您不会获取地址,只需直接复制它]。

但是,你必须非常小心你存储的指针的生命周期,正如初始点所证明的那样。

答案 5 :(得分:0)

您要实现的是堆栈上的动态数组。您想要创建一个对象列表,并且不在堆中保留它们。 C ++不支持这一点,至少不在一个函数的范围内。

您可以使用递归重构代码并保持链接列表在堆栈中上升,但这不会是C ++ -ish。

否则,唯一的解决方案是使用堆(std::liststd::auto_ptrstd::unique_ptr应该这样做),正如其他人所建议的那样。