trouble assigning reference

C

Christopher

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?
 
J

joshuamaurice

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.
 
C

Christopher

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.
 
N

Neelesh

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.
 
C

Christopher

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.

















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;
}
 
N

Neelesh

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".
 
N

Neelesh

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.
 
N

Neelesh

Typo correction:

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*.
 
V

Vladimir Jovic

Neelesh said:
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.
 
N

Neelesh

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".
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,899
Latest member
RodneyMcAu

Latest Threads

Top