trouble assigning reference

Discussion in 'C++' started by Christopher, May 7, 2009.

  1. Christopher

    Christopher Guest

    I am getting an odd compiler error:
    'Pass::eek:perator =' : cannot access private member declared in class
    'Pass'

    It is speaking as if I am trying to assign a Pass object to Pass
    another object, but I am trying to assign a reference to another
    reference.


    //----------------------------------------------------------------------------
    class Pass
    {
    public:

    /** Only a Technique should construct a Pass */
    friend class Technique;

    ~Pass();

    // Snip

    private:

    /**
    * Constructor
    *
    * Only a Technique should construct a Pass
    **/
    Pass(ID3D10EffectPass * pass);

    /* No copy not allowed */
    Pass(const Pass & rhs);

    /** No assignment allowed */
    Pass & operator = (const Pass & rhs);

    // SNIP
    };

    class PolygonSet
    {
    // SNIP

    protected:

    // SNIP

    struct PassInfo
    {
    PassInfo(Pass & pass, const std::vector<unsigned> &
    vertexBufferIndices, ID3D10InputLayout * inputLayout);
    PassInfo(const PassInfo & rhs);
    PassInfo & operator = (const PassInfo & rhs);

    Pass & m_pass; // A
    single pass from a technique
    std::vector<unsigned> m_vertexBufferIndices; // Which buffers
    provide the data required for the pass
    ID3D10InputLayout * m_inputLayout; // Input layout
    used for a specific pass
    };
    };

    //------------------------------------------------------------------------------------------
    PolygonSet::passInfo & PolygonSet::passInfo::eek:perator = (const
    PassInfo & rhs)
    {
    m_pass =
    rhs.m_pass; // PROBLEM HERE
    m_vertexBufferIndices = rhs.m_vertexBufferIndices;
    m_inputLayout = rhs.m_inputLayout;

    return *this;
    }



    I don't understand why it is not letting me assign a reference to
    another reference. I don't ever have problems doing that in a
    constructor's initialization list. What's going on here?
     
    Christopher, May 7, 2009
    #1
    1. Advertising

  2. Christopher

    Guest

    On May 6, 5:29 pm, Christopher <> wrote:
    > I am getting an odd compiler error:
    > 'Pass::eek:perator =' : cannot access private member declared in class
    > 'Pass'

    [snip]
    > I don't understand why it is not letting me assign a reference to
    > another reference. I don't ever have problems doing that in a
    > constructor's initialization list. What's going on here?


    References cannot be changed to point to something new after they're
    created. Specifically, take the code fragment
    int a;
    int b;
    int & ra = a;
    int & rb = b;
    ra = rb;
    "ra = rb;" does not change reference ra to alias the object aliased by
    rb. Instead, the references act like the objects being aliased. "ra =
    rb;" takes the b object and assigns that to the a object.

    If you want to change what a reference aliases, then you need
    pointers.
     
    , May 7, 2009
    #2
    1. Advertising

  3. Christopher

    Christopher Guest

    On May 6, 7:35 pm, wrote:
    > References cannot be changed to point to something new after they're
    > created. Specifically, take the code fragment
    >     int a;
    >     int b;
    >     int & ra = a;
    >     int & rb = b;
    >     ra = rb;
    > "ra = rb;" does not change reference ra to alias the object aliased by
    > rb. Instead, the references act like the objects being aliased. "ra =
    > rb;" takes the b object and assigns that to the a object.
    >
    > If you want to change what a reference aliases, then you need
    > pointers.


    Crap. I hope I don't have to change the interfaces all the way down
    the hierarchy.
    Can I assign a pointer to point to an object, which a refereance
    aliases?

    I have a class "technique" that creates and manages the lifetime of
    "pass" objects. I don't want anyone else constructing, deconstructing,
    or changing the data of these pass objects, except the "technique"
    that created it.

    However, other classes need access to the information contained by the
    "pass" class. So, I made a method in "technique" that returns a const
    reference to a pass that it manages.

    Now I have a "PassInfo" class that needs to be able to make calls and
    access the info contained by a "pass", it doesn't need to change it,
    but only access it. These "PassInfo" objects are stored in a
    std::vector. So my problem is implementing the requirements of a class
    that can be stored in the vector for "passinfo" without breaking the
    rules for the "pass"

    Phew, I hope that makes sense.
     
    Christopher, May 7, 2009
    #3
  4. Christopher

    Neelesh Guest

    On May 7, 5:29 am, Christopher <> wrote:
    > I am getting an odd compiler error:
    > 'Pass::eek:perator =' : cannot access private member declared in class
    > 'Pass'
    >
    > It is speaking as if I am trying to assign a Pass object to Pass
    > another object, but I am trying to assign a reference to another
    > reference.
    >


    Reference is not something "different" than an object, a reference is
    simply an alias (i.e. a different name) for an object. More
    importantly, once an alias gets associated with an object, it cannot
    get associated with any other object. Hence, assigning a reference is
    effectively assigning the objects for which they are aliases.

    > //-------------------------------------------------------------------------­---
    > class Pass
    > {
    > public:
    >
    >    /** Only a Technique should construct a Pass */
    >    friend class Technique;
    >
    >    ~Pass();
    >
    >    // Snip
    >
    > private:
    >
    >    /**
    >    * Constructor
    >    *
    >    * Only a Technique should construct a Pass
    >    **/
    >    Pass(ID3D10EffectPass * pass);
    >
    >    /* No copy not allowed */
    >    Pass(const Pass & rhs);
    >
    >    /** No assignment allowed */
    >    Pass & operator = (const Pass & rhs);
    >
    >    // SNIP
    >
    > };
    >
    > class PolygonSet
    > {
    >   // SNIP
    >
    >   protected:
    >
    >   // SNIP
    >
    >   struct PassInfo
    >   {
    >      PassInfo(Pass & pass, const std::vector<unsigned> &
    > vertexBufferIndices, ID3D10InputLayout * inputLayout);
    >      PassInfo(const PassInfo & rhs);
    >      PassInfo & operator = (const PassInfo & rhs);
    >
    >      Pass &                      m_pass;                       // A
    > single pass from a technique
    >      std::vector<unsigned> m_vertexBufferIndices;   // Which buffers
    > provide the data required for the pass
    >      ID3D10InputLayout *   m_inputLayout;              // Input layout
    > used for a specific pass
    >    };
    >
    > };
    >
    > //-------------------------------------------------------------------------­-----------------
    > PolygonSet::passInfo & PolygonSet::passInfo::eek:perator = (const
    > PassInfo & rhs)
    > {
    >    m_pass                     =
    > rhs.m_pass;                          // PROBLEM HERE
    >    m_vertexBufferIndices = rhs.m_vertexBufferIndices;
    >    m_inputLayout           = rhs.m_inputLayout;
    >
    >    return *this;
    >
    > }
    >
    > I don't understand why it is not letting me assign a reference to
    > another reference. I don't ever have problems doing that in a
    > constructor's initialization list. What's going on here?


    Because constructor initialization list is a place where, for the
    first time, we give meaning to a reference. In other words, you tell
    that reference whose alias it is. (Remember that there cannot be null
    references, and hence every reference member must be explicitly
    initialized in the constructor initialization list). Once that is
    done, there is no way one can "separate out" the reference from the
    object. Thus, any time other than a constructor initialization list,
    any attempt to assign a reference effectively results in assigning
    objects. References are not pointers.
     
    Neelesh, May 7, 2009
    #4
  5. Christopher

    Christopher Guest

    On May 6, 10:32 pm, Neelesh <> wrote:
    > On May 7, 5:29 am, Christopher <> wrote:
    >
    > > I am getting an odd compiler error:
    > > 'Pass::eek:perator =' : cannot access private member declared in class
    > > 'Pass'

    >
    > > It is speaking as if I am trying to assign a Pass object to Pass
    > > another object, but I am trying to assign a reference to another
    > > reference.

    >
    > Reference is not something "different" than an object, a reference is
    > simply an alias (i.e. a different name) for an object. More
    > importantly, once an alias gets associated with an object, it cannot
    > get associated with any other object. Hence, assigning a reference is
    > effectively assigning the objects for which they are aliases.
    >
    >
    >
    >
    >
    > > //-------------------------------------------------------------------------­­---
    > > class Pass
    > > {
    > > public:

    >
    > >    /** Only a Technique should construct a Pass */
    > >    friend class Technique;

    >
    > >    ~Pass();

    >
    > >    // Snip

    >
    > > private:

    >
    > >    /**
    > >    * Constructor
    > >    *
    > >    * Only a Technique should construct a Pass
    > >    **/
    > >    Pass(ID3D10EffectPass * pass);

    >
    > >    /* No copy not allowed */
    > >    Pass(const Pass & rhs);

    >
    > >    /** No assignment allowed */
    > >    Pass & operator = (const Pass & rhs);

    >
    > >    // SNIP

    >
    > > };

    >
    > > class PolygonSet
    > > {
    > >   // SNIP

    >
    > >   protected:

    >
    > >   // SNIP

    >
    > >   struct PassInfo
    > >   {
    > >      PassInfo(Pass & pass, const std::vector<unsigned> &
    > > vertexBufferIndices, ID3D10InputLayout * inputLayout);
    > >      PassInfo(const PassInfo & rhs);
    > >      PassInfo & operator = (const PassInfo & rhs);

    >
    > >      Pass &                      m_pass;                       // A
    > > single pass from a technique
    > >      std::vector<unsigned> m_vertexBufferIndices;   // Which buffers
    > > provide the data required for the pass
    > >      ID3D10InputLayout *   m_inputLayout;              // Input layout
    > > used for a specific pass
    > >    };

    >
    > > };

    >
    > > //-------------------------------------------------------------------------­­-----------------
    > > PolygonSet::passInfo & PolygonSet::passInfo::eek:perator = (const
    > > PassInfo & rhs)
    > > {
    > >    m_pass                     =
    > > rhs.m_pass;                          // PROBLEM HERE
    > >    m_vertexBufferIndices = rhs.m_vertexBufferIndices;
    > >    m_inputLayout           = rhs.m_inputLayout;

    >
    > >    return *this;

    >
    > > }

    >
    > > I don't understand why it is not letting me assign a reference to
    > > another reference. I don't ever have problems doing that in a
    > > constructor's initialization list. What's going on here?

    >
    > Because constructor initialization list is a place where, for the
    > first time, we give meaning to a reference. In other words, you tell
    > that reference whose alias it is. (Remember that there cannot be null
    > references, and hence every reference member must be explicitly
    > initialized in the constructor initialization list). Once that is
    > done, there is no way one can "separate out" the reference from the
    > object. Thus, any time other than a constructor initialization list,
    > any attempt to assign a reference effectively results in assigning
    > objects. References are not pointers.- Hide quoted text -
    >
    > - Show quoted text -


    Ok, I think I understand the problem.
    Two more questions though:

    1) I think I can have a null reference. What can i expect when this
    happens:

    #include <iostream>

    int main()
    {
    int * ptr = new int(7);
    int & ref = *ptr;
    delete ptr;

    // more stuff

    std::cout << ref << std::endl;
    }

    2) Is this safe?

    #include <iostream>

    class A
    {
    public:

    A() { m_ptr = new int(9); }
    ~A() { delete m_ptr; }

    const int & GetInt() const { return *m_ptr; }

    private:

    int * m_ptr;
    };

    int main()
    {
    A a();
    int * anotherPtr = &(a.GetInt());

    std::cout << *anotherPtr << std::endl;

    return 0;
    }
     
    Christopher, May 7, 2009
    #5
  6. Christopher

    Neelesh Guest

    On May 7, 5:50 am, Christopher <> wrote:
    > On May 6, 7:35 pm, wrote:
    >
    > > References cannot be changed to point to something new after they're
    > > created. Specifically, take the code fragment
    > >     int a;
    > >     int b;
    > >     int & ra = a;
    > >     int & rb = b;
    > >     ra = rb;
    > > "ra = rb;" does not change reference ra to alias the object aliased by
    > > rb. Instead, the references act like the objects being aliased. "ra =
    > > rb;" takes the b object and assigns that to the a object.

    >
    > > If you want to change what a reference aliases, then you need
    > > pointers.

    >
    > Crap. I hope I don't have to change the interfaces all the way down
    > the hierarchy.
    > Can I assign a pointer to point to an object, which a refereance
    > aliases?
    >


    Yes.

    int a;
    int &b = a;
    int *c = &b; //Same as int* c = &a;

    > I have a class "technique" that creates and manages the lifetime of
    > "pass" objects. I don't want anyone else constructing, deconstructing,
    > or changing the data of these pass objects, except the "technique"
    > that created it.
    >
    > However, other classes need access to the information contained by the
    > "pass" class. So, I made a method in "technique" that returns a const
    > reference to a pass that it manages.
    >
    > Now I have a "PassInfo" class that needs to be able to make calls and
    > access the info contained by a "pass", it doesn't need to change it,
    > but only access it. These "PassInfo" objects are stored in a
    > std::vector. So my problem is implementing the requirements of a class
    > that can be stored in the vector for "passinfo" without breaking the
    > rules for the "pass"
    >


    Instead of having a Pass& in the struct PassInfo, use a pointer-to-
    const. A (non-const)pointer can point to a different object, and a
    pointer-to-const will make sure that you donot use that pointer to
    change the "Pass" object that it points to, since you essentially
    donot want the PassInfo object to change the Pass object associated
    with it.

    You may find these useful:
    http://www.parashift.com/c -faq-lite/references.html#faq-8.2 : About
    "assiging a reference"
    http://www.parashift.com/c -faq-lite/references.html#faq-8.6 : About
    "pointers vs. references".
     
    Neelesh, May 7, 2009
    #6
  7. Christopher

    Neelesh Guest

    On May 7, 8:47 am, Christopher <> wrote:
    >
    >
    > Two more questions though:
    >
    > 1) I think I can have a null reference.


    No. The C++ standard clearly says that "null reference cannot exist in
    a well-defined program" (8.3.2p4)
    Note that a reference can never be null, it can refer to a pointer
    that can be null.

    >What can i expect when this
    > happens:
    >
    > #include <iostream>
    >
    > int main()
    > {
    >    int * ptr = new int(7);
    >    int & ref = *ptr;
    >    delete ptr;
    >
    >    // more stuff
    >
    >    std::cout << ref << std::endl;
    >
    > }
    >


    This is an undefined behaviour, since you are trying to dereference
    the pointer ptr after deleting it.

    > 2) Is this safe?
    >


    > #include <iostream>
    >
    > class A
    > {
    > public:
    >
    >    A() { m_ptr = new int(9); }
    >    ~A() { delete m_ptr; }
    >
    >    const int & GetInt() const { return *m_ptr; }
    >
    > private:
    >
    >    int * m_ptr;
    >
    > };
    >
    > int main()
    > {
    >    A a();


    Beware - You think you are defining an object of type A using the 0-
    arg constructor, but the compiler thinks something totally different.
    The compiler treats this as a function declaraction for a function a
    that takes nothing and returns a.

    If you want to declare a variable representing an object of type a,
    simply say
    A a;

    >    int * anotherPtr = &(a.GetInt());


    This line gives error since a is a treated as a function by the
    compiler and there is no way it can have GetInt member function.
    Changing A a() to A a will remove this error, but still there is one
    more error. Observe that GetInt function returns a reference to a
    const-int. Hence, &(a.GetInt()) has type "pointer-to-const". A pointer-
    to-const cannot be assigned to a pointer-to-non-const. You will need
    to change int * anotherPtr to const int* anotherPtr to make this line
    compile.

    >
    >    std::cout << *anotherPtr << std::endl;
    >
    >    return 0;
    >
    > }


    Finally, it is OK to have anotherPtr as long as you donot delete
    anotherPtr or try to dereference it after the object "a" ceases to
    exist. But this kind of usage might unknowingly lead you in trouble,
    specifically if you aren't sure what all places is this pointer being
    used.

    Thanks.
     
    Neelesh, May 7, 2009
    #7
  8. Christopher

    Neelesh Guest

    Typo correction:
    On May 7, 9:24 am, Neelesh <> wrote:
    > > 2) Is this safe?

    >
    > > #include <iostream>

    >
    > > class A
    > > {
    > > public:

    >
    > >    A() { m_ptr = new int(9); }
    > >    ~A() { delete m_ptr; }

    >
    > >    const int & GetInt() const { return *m_ptr; }

    >
    > > private:

    >
    > >    int * m_ptr;

    >
    > > };

    >
    > > int main()
    > > {
    > >    A a();

    >


    Beware - You think you are defining an object of type A using the 0-
    arg constructor, but the compiler thinks something totally different.
    The compiler treats this as a function declaraction for a function a
    that takes nothing and returns *an object of type A by value*.

    > [...]
     
    Neelesh, May 7, 2009
    #8
  9. Neelesh wrote:
    > On May 7, 8:47 am, Christopher <> wrote:
    >>
    >> Two more questions though:
    >>
    >> 1) I think I can have a null reference.

    >
    > No. The C++ standard clearly says that "null reference cannot exist in
    > a well-defined program" (8.3.2p4)
    > Note that a reference can never be null, it can refer to a pointer
    > that can be null.


    1)

    int *a=NULL;
    int &b = *a;

    2)

    int *a = NULL;
    int *&b = a;


    Which one you had on your mind here?
    The 1) causes an undefined behaviour.
     
    Vladimir Jovic, May 7, 2009
    #9
  10. Christopher

    Neelesh Guest

    On May 7, 3:44 pm, Vladimir Jovic <> wrote:
    > Neelesh wrote:
    > > On May 7, 8:47 am, Christopher <> wrote:

    >
    > >> Two more questions though:

    >
    > >> 1) I think I can have a null reference.

    >
    > > No. The C++ standard clearly says that "null reference cannot exist in
    > > a well-defined program" (8.3.2p4)
    > > Note that a reference can never be null, it can refer to a pointer
    > > that can be null.

    >
    > 1)
    >
    > int *a=NULL;
    > int &b = *a;
    >


    a is a null pointer, b is a reference to an integer. Since b is
    initialized by dereferncing a null pointer, it is undefined what value
    would b have. Therefore the program also has undefined behavior.

    > 2)
    >
    > int *a = NULL;
    > int *&b = a;
    >


    a is a null pointer, b is a reference to an integer pointer, and b is
    initialized as a null pointer. In other words, b is a "valid"
    reference to a "null pointer". But that doesnot make b a "null
    reference".

    > Which one you had on your mind here?
    > The 1) causes an undefined behaviour.


    In neither of the two cases, "the reference is null". In fact, a
    reference can never be "null".
     
    Neelesh, May 7, 2009
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. fAbs
    Replies:
    17
    Views:
    573
  2. Dave

    Assigning to a reference

    Dave, Nov 6, 2003, in forum: C++
    Replies:
    5
    Views:
    391
    =?iso-8859-1?Q?Juli=E1n?= Albo
    Nov 6, 2003
  3. Protoman
    Replies:
    14
    Views:
    617
    n2xssvv g02gfr12930
    Nov 27, 2005
  4. Replies:
    12
    Views:
    498
  5. weston
    Replies:
    1
    Views:
    278
    Richard Cornford
    Sep 22, 2006
Loading...

Share This Page