【问题标题】:C++: References as constructor arguments, helpC++:作为构造函数参数的引用,帮助
【发布时间】:2010-07-07 16:00:44
【问题描述】:

我有一个基类(Base),它的构造函数将引用作为参数。在我的派生类它的构造函数中,我调用超类构造函数,当然我需要传递一个引用作为参数。但是我必须从返回类型为按值的方法中获取该参数...

我将举一个简短的例子:

class Base
{
public:
    Base(MyType &obj) { /* do something with the obj */}
};

class Derived : public Base
{
public:
    Derived(MyOtherType *otherType) :
         Base(otherType->getMyTypeObj()) // <--- Here is the error because (see *)
    {
         // * 
         // getMyTypeObj() returns a value and
         // the Base constructor wants a reference...
    }
};

class MyOtherType
{
public:
    MyType getMyTypeObj()
    {
         MyType obj;
         obj.setData( /* blah, blah, blah... Some data */);
         return obj; // Return by value to avoid the returned reference goes out of scope.
    }
};

我该如何解决这个问题?

【问题讨论】:

  • Base 构造函数是否修改对象,它获得的引用?有什么限制?我的意思是,您可以修改代码的哪些部分,哪些部分必须保持不变?
  • 使参数成为常量引用。
  • const 参考有什么帮助?它仍然是对不再存在的事物的引用。
  • @Michael 不,不是。如果使用 const 引用,则可以将该引用绑定到临时引用,例如返回值。他不能做的是将该引用存储在正在构造的对象中,但我不清楚他正在做什么。
  • @Neil - 我认为只要构造函数运行,const 引用就会存在,但我们不知道基本构造函数是否保存了一些引用以供以后使用。

标签: c++ constructor reference argument-passing


【解决方案1】:

将基类更改为: class Base { public: Base(const MyType &obj) { /* do something with the obj */} };

更新:如果你想修改 obj 你显然不能有 const 引用。在这种情况下,您可以:

1)按值传递参数。这将产生副本的开销,但避免以后必须显式释放它。

2) 将MyOtherType::getMyTypeObj() 更改为

MyType& MyOtherType::getMyTypeObj()
{
    MyType* obj = new MyType();
    obj->setData( /* blah, blah, blah... Some data */);
    return *obj;

}

在这种情况下,请记住在完成后删除该对象。

【讨论】:

  • 这会起作用,除非/* do something with the obj */ 意味着他想修改 obj。
  • 当然。但是,如果他想修改对象,他可能最好制作自己的副本。更新了我的答案。谢谢
【解决方案2】:

真的吗?你的问题有答案。将参数的类型更改为 Base 构造函数,或者更改 getMyTypeObj() 的返回值的类型,以便类型兼容。

【讨论】:

  • +1:这似乎是您的全部代码,那么为什么要解决您可以解决的问题呢?
【解决方案3】:

问题是由 GetMyTypeObj() 返回一个基于堆栈的 'obj' 的副本引起的,因此编译器在您的构造函数中创建了一个临时变量,其范围就是那个 Base() 构造调用。

【讨论】:

    【解决方案4】:

    在我看来有两种方法可以解决这个问题。

    1. 将 Base 构造函数更改为按值而不是按引用接受 MyType 对象。这将复制临时对象并解决范围问题。

    2. 或者,您可以在 Derived 中复制 MyType 对象并传递对它的引用。

    class Derived : public Base
    {
    public:
        Derived(MyOtherType *otherType) :
            Base(m_myType) ,
            m_myType(otherType->getMyTypeObj())
        {
            // ...
        }
    private:
        MyType m_myType;
    };
    

    选项 1 更简单,我通常会推荐它。
    选项 2 以防万一其他约束阻止您更改 Base 构造函数,

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-20
      • 1970-01-01
      相关资源
      最近更新 更多