【问题标题】:How I set a reference after constructor?如何在构造函数之后设置引用?
【发布时间】:2018-05-11 16:40:37
【问题描述】:

我想在构造函数之后设置一个引用

示例:

class OtherClass
{
public:
    OtherClass() : m_class(Class()){}

    inline void SetData(int data1, int data2)
    {
        //calculate data3

        // I tried:
        m_class = Class(data3);
        //but it doesn't worked
    }

protected:
private:
    Class& m_class;
};

编辑:

  • 例外是:向量下标超出范围 因为我在课堂上有 glm 向量。
  • 我还需要在我的类中调用函数。

编辑 2:

我为什么需要这个? 因为我有另一个类 [ExClass] 扩展并且必须在构造函数中计算:

ExClass::ExClass(float d1, float d2, ...) {
//calculate data from given values
SetData(data); 
}

【问题讨论】:

  • 您的错误信息是什么? 'Class' 是否有 (int,int) 的构造函数?
  • 你为什么要把它作为一个参考?
  • 感谢您的 cmets。我简化了示例,我正在使用我的顶点类。 例外是:向量下标超出范围
  • (我的 Vertex 类中有 glm 向量)
  • 这个问题很不清楚。目前尚不清楚您正在尝试做什么,也不清楚它是如何不起作用的。请edit您的问题提供minimal reproducible example以及明确的问题陈述。

标签: c++ reference


【解决方案1】:

正确的方法是使用指针而不是引用,而不是引用——指针可以在对象创建后设置。另请注意,引用(或指向)一个生命周期将结束但仍在使用的局部变量是一个坏主意。

您的代码可能会更改为使用指针和动态分配或std::unique_ptr。当然还有其他选择,这些只是示例。

选项 1 - 指针和动态分配

class OtherClass
{
public:
    OtherClass() : m_class(nullptr){}
    ~OtherClass() {
        delete m_class;
    }

    // block copy and assignment (or implement them)
    OtherClass(const OtherClass&) = delete;
    OtherClass& operator=(const OtherClass&) = delete;

    void setData(int data1, int data2)
    {
        // ... calculate data3 ...

        m_class = new Class(data3);
    }
    bool hasInnerObj() const {
        return m_class; // or: return m_class != nullptr;
    }
    /** call this function only if hasInnerObj() returned true */
    Class& getInnerObj() {
        return *m_class;
    }
private:
    Class* m_class;
};

选项 2 - std::unique_ptr

class OtherClass
{
public:
    void setData(int data1, int data2)
    {
        // ... calculate data3 ...

        m_class = std::make_unique<Class>(data3);
    }
    bool hasInnerObj() const {
        return m_class; // or: return m_class != nullptr;
    }
    /** call this function only if hasInnerObj() returned true */
    Class& getInnerObj() {
        return *m_class;
    }
private:
    std::unique_ptr<Class> m_class;
};

【讨论】:

    【解决方案2】:

    你有两个问题:

    1. 在创建对象时需要初始化引用类成员(即m_class)。
    2. 但是,您的两个 Class 实例(一个在构造函数中,一个在 SetData 中)都被放入堆栈并立即弹出,导致引用无效。

    您需要做的是确保您的类对象实际上通过函数调用存在。实现这一点的一种方法是在将其传递给 OtherClass 构造函数或 SetData 函数之前对其进行分配:

    class Class {};
    
    class OtherClass
    {
    public:
        OtherClass(Class& c) : m_class(c){}
    
        inline void SetData(Class& c)
        {
            m_class = c;
        }
    
    protected:
    private:
        Class& m_class;
    };
    
    int main()
    {
        Class a;
        OtherClass c(a);
    
        Class b;
        c.SetData(b); // changes m_class
    
        return 0;
    }
    

    Live example here.

    【讨论】:

    • 这不是 OP 想要的,我怀疑,不是你想要的。它将main() 中定义的Class a 更改为在main() 中具有Class b 的内容。我认为他希望Class&amp; m_class 先引用a,然后再引用b,这是做不到的。换句话说,注释“更改 m_class”是错误的。它改变了 m_class 所引用的对象,即 'a'。
    • @JiveDadson 更改a(或当前持有的任何引用m_class)可能是也可能不是有意的。你的猜测和我的一样好。由于他正在使用代表位置的vector3 的东西,我猜在这一点上,他想要Class m_class 而不是Class &amp;m_class
    猜你喜欢
    • 2011-07-20
    • 2015-06-04
    • 2012-06-11
    • 2018-02-20
    • 2011-05-08
    • 1970-01-01
    • 2017-07-11
    • 1970-01-01
    • 2016-07-16
    相关资源
    最近更新 更多