Sign in to follow this  
chadsxe

How do you initialize a reference type in default constructor?

Recommended Posts

Kinda hard to explain but I am getting this error error C2758: 'Graphics::m_applicationReference' : must be initialized in constructor base/member initializer list
class Application;

class Graphics
{
	public:
		Graphics();
		Graphics(Application &applicationRef);
		Graphics(const Graphics &graphicsClass);
		Graphics& operator= (const Graphics &graphicsClass);
		~Graphics();
	private:
		Application &m_applicationReference;	// Ref to the application

};

Graphics::Graphics()
{
   // Error C2758 points to hear
   // How am I suppose to initialize a reference type?
}
Graphics::Graphics(Application &applicationRef)
: m_applicationReference(applicationRef)
{
}
Graphics::Graphics(const Graphics &graphicsClass)
: m_applicationReference(graphicsClass.m_applicationReference)
{
}
Graphics& Graphics::operator= (const Graphics &graphicsClass)
{
	// do the copy
	m_applicationReference = graphicsClass.m_applicationReference;
	// return the existing object
	return *this;
}
It appears to be telling me I need to initialize m_applicationReference in my Default Consttuctor. But I have no clue how to accomplish that. Any suggestion? Regards Chad

Share this post


Link to post
Share on other sites
If you use or plan to use the default constructor or you plan to use the assignment or copy constructor, you should use a pointer to the application instead. Otherwise remove the default constructor, assignment, and copy constructor.

This also doesn't do what you think it does (or could be fatal):

Graphics& Graphics::operator= (const Graphics &graphicsClass)
{
// do the copy
m_applicationReference = graphicsClass.m_applicationReference;
}




Use a pointer instead.

Share this post


Link to post
Share on other sites
Quote:
Original post by _fastcall
If you use or plan to use the default constructor or you plan to use the assignment or copy constructor, you should use a pointer to the application instead. Otherwise remove the default constructor, assignment, and copy constructor.

This also doesn't do what you think it does (or could be fatal):
*** Source Snippet Removed ***

Use a pointer instead.


So now you got me worried. What am I doing wrong with the operator= ?

You also suggest using pointers. How does this look.
Graphics::Graphics()
{
}
Graphics::Graphics(Application *applicationRef)
: m_applicationPointer(applicationRef)
{
}
Graphics::Graphics(const Graphics &graphicsClass)
: m_applicationPointer(graphicsClass.m_applicationPointer)
{
}
Graphics& Graphics::operator= (const Graphics &graphicsClass)
{
// do the copy
m_applicationPointer = graphicsClass.m_applicationPointer;
// return the existing object
return *this;
}
I am guessing there is still something wrong with the operator=

Any suggestion?

Regards

Chad

Share this post


Link to post
Share on other sites
The problem isn't the graphics class, but rather the big picture. Are you really planning on instantiating a graphics class, then initializing the application pointer/reference later? If so, then you must use a pointer. Are you really planning on copying a graphics class? If so, then you must use a pointer (see assignment operators, and references). Are you really planning on juggling and moving more than one graphics instance? If you answered no to all of these questions, then it is fine to use a reference, just remove the copy constructor, assignment operator, and the default constructor.

Share this post


Link to post
Share on other sites
Quote:
Original post by _fastcall
The problem isn't the graphics class, but rather the big picture. Are you really planning on instantiating a graphics class, then initializing the application pointer/reference later? If so, then you must use a pointer. Are you really planning on copying a graphics class? If so, then you must use a pointer (see assignment operators, and references). Are you really planning on juggling and moving more than one graphics instance? If you answered no to all of these questions, then it is fine to use a reference, just remove the copy constructor, assignment operator, and the default constructor.


O.k bear with me...I might not be understanding the best way to do this...

I am trying to store a reference/pointer to a class object in another class object. Lets say I ahve something like

//A.h
class A
{
A(B b)
{
this.b = b;
}

B b;
}

//B.h
class B
{
B();
A a; // How the heck do I initalize the A object with the the current B object
// I need to do this a(b) some place but I dont know how to.
}
What is throwing me for the curve is that I am declaring an A object in class B but I can't pass arguments to to the A objects constructor because it resides in my .h file. Is there a way to pass the argument to the constructor? I thought the only way to do that was the way I was going about it.

Does this make sense?

Regards

Chad

Share this post


Link to post
Share on other sites
Take a step back. The code you just posted has an B in every A, and a A in every B. This won't work - this will go on forever!

Did you miss out some &s to mark references?

Share this post


Link to post
Share on other sites
Quote:
Original post by Codeka
Remove the default constructor.

Edit: too slow!
The default constructor can still be used but the only things you could initialise the reference with would be a global or static variable, or new object, or an object obtained through some other function call.
However the first two of those would defeat the point of having it as a reference, the third would give you unique instances rather than shared ones, and the fourth doesn't really give any bennefits either. So yeah, remove the default constructor, or reconsider pointers instead.

Share this post


Link to post
Share on other sites
Quote:
Original post by mattd
Take a step back. The code you just posted has an B in every A, and a A in every B. This won't work - this will go on forever!

Did you miss out some &s to mark references?


Sorry I did not put them in there because I was not sure if I was going to be using a * or a & . I instead wrote that out in my text explanation.

Sorry for the confusion.

Regards

Chad

Share this post


Link to post
Share on other sites
Then you could do (I think this you want you wanted - B contains a A, while A has the reference back to B:


//A.h
class A
{
A(B& b) : b(b) {}

B& b;
}



//B.h
class B
{
B() : a(*this) {}

A a;
}



But be careful with what you do with that reference that comes from B's this pointer in A's constructor.

Share this post


Link to post
Share on other sites
Quote:
Original post by iMalc
Quote:
Original post by Codeka
Remove the default constructor.

Edit: too slow!
The default constructor can still be used but the only things you could initialise the reference with would be a global or static variable, or new object, or an object obtained through some other function call.

I just looked up the Holy Standard, because I thought the following would be legal:
    struct Foo {
int &r;
Foo () : r(r) {}
};

But it is not:
Quote:
ISO/IEC 14882:2003(E), 8.3.2.4
There shall be no references to references [...]A reference shall be initialized to refer to a valid object
or function. [Note: in particular, a null reference cannot exist in a well-defined program, because the only way to create such a reference would be to bind it to the “object” obtained by dereferencing a null pointer, which causes undefined behavior. [...] ]


So forget what I did not recommend :S


Quote:
However the first two of those would defeat the point of having it as a reference, the third would give you unique instances rather than shared ones, and the fourth doesn't really give any bennefits either. So yeah, remove the default constructor, or reconsider pointers instead.

It is interesting to note that if you put a reference into a class definition ...

    struct Foo {
char &c;
};


... then this perfectly prevents the compiler from generating a default constructor behind the back:

Quote:
12.1
[...]
5 - A default constructor for a class X is a constructor of class X that can be called without an argument.
[...]
7 - Before the implicitly-declared default constructor for a class is implicitly
defined, all the implicitly-declared default constructors for its base classes and its nonstatic data members shall have been implicitly defined.
[...]



And as initializing a const or a reference member with an empty argument list made your program ill-formed, the compiler won't derive it implicitly. Same argumentation for copy assigment (T& operator = (T const &)).

Share this post


Link to post
Share on other sites
Thanks to all...

After spending a few hours reading through the reference and testing some stuff. I belive a pointer is what I am looking for. I have added a check for self assignment so thanks for the heads up on that one. And thanks to anyone else who helped with the learning.

Regards

Chad

Share this post


Link to post
Share on other sites
Quote:

But it is not:


I very much doubt that your interpretation is correct, or all my understanding of C++ just broke apart and all my code turned out to be ill-formed. Haven't you done things like:

vec1.push_back(vec2[i]); 


I suppose this means that something like the following doesn't compile:


int main()
{
int a;
int& b= a;
int& & c = b;
}


If you remove the second & from the declaration of c, it will be OK, and c will be a reference to the same object as b, namely a.

Share this post


Link to post
Share on other sites
Quote:
Original post by visitor
I suppose this means that something like the following doesn't compile:


int main()
{
int a;
int& b= a;
int& & c = b;
}


If you remove the second & from the declaration of c, it will be OK, and c will be a reference to the same object as b, namely a.


I guess this is about "reference to reference", which is indeed not allowed. The line
    int &b=a;

reads more like "dereference the rhs, and build a reference from it", which is why
    int main () {
int a, &b = a, &c = b;
}
is a well-formed program, and from that standpoint the reason why you cannot build a reference from a temporary (because a temporary has no address).


But my point was more about
Quote:
A reference shall be initialized to refer to a valid object or function

and as in
    struct Foo { int &p; Foo () : p(p){} };

or more precise
    p(p)

p is not a readily constructed entity (neither as a reference, nor as an value) and hence an invalid object, and thus not de-referenceable, that initialization is ill-formed.

Share this post


Link to post
Share on other sites
Missed that you were in fact demonstrating an attempt to initialize a reference to basically nothing. Yep, initializing anything with itself doesn't do any good.


int a = a;


Still uninitialized.

Share this post


Link to post
Share on other sites
Foo & default_instance() {
static Foo instance;
return instance;
};

struct Bar {
Bar(Foo & ref = default_instance());
};

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this