473,386 Members | 1,962 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

Passing *this in constructor

Hi, thanks for help in previous post. I've made the class objects i
need data members so
i now initialise in constructor. However some of my subobjects need to
have a reference to their
owner object.

Can i do the following then ie pass *this in the constructor of A, i
was concerned maybe the
A object is not fully constructed. If this is not way to do how to do?

/.h file
class A
{
public:
A();
~A();
private:

obj1 myobj1;

};
/.cpp file

A::A()
: myobj1(*this) <- CHANGE MADE HERE
{

}

A::~A()
{
}
Obviously constructor of obj1 takes reference to A

class obj1
{
private:
obj1& m_obj;
};

obj1(A& a):m_obj(a)
{
}

Jun 27 '08 #1
7 1619
tech wrote:
Hi, thanks for help in previous post. I've made the class objects i
need data members so
i now initialise in constructor. However some of my subobjects need to
have a reference to their
owner object.

Can i do the following then ie pass *this in the constructor of A, i
was concerned maybe the
A object is not fully constructed. If this is not way to do how to do?

/.h file
class A
{
public:
A();
~A();
private:

obj1 myobj1;

};
/.cpp file

A::A()
: myobj1(*this) <- CHANGE MADE HERE
{

}

A::~A()
{
}
Obviously constructor of obj1 takes reference to A

class obj1
{
private:
obj1& m_obj;
I think you meant

A& m_obj;
};

obj1(A& a):m_obj(a)
{
}


The answer is "Yes, you can". Be careful, though, not to call any
member functions or access any data members of 'a' in the 'obj1'
constructor because 'a' hasn't been fully constructed yet.
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jun 27 '08 #2
Hi!

James Kanze schrieb:
The answer is "yes, you can" in this simple case. If the object
expects a reference to a base class, however, you have undefined
behavior (and I've encountered cases where it doesn't work),
since conversion to base is also undefined behavior.
Wait a second. What's that? Has the following undefined behaviour?

struct Foo {
private:
//..lots of member variables needing initialisation
string name;
Bar whatever;
protected:
void run();
};

struct Runner : Foo
{
Runner();
~Runner();
boost::thread myThread;
};

Runner::Runner()
: Foo()
, myThread(bind(&Foo::run, this))
{}
Runner::~Runner()
{
myThread.interrupt();
myThread.join();
}

Maybe this doesn't actually force the conversion of "this" to "Foo*",
but it's an example of what I currently need in some code. I just want
to know some rules about this. So when does it become dangerous?

Frank
Jun 27 '08 #3
Frank Birbacher wrote:
Hi!

James Kanze schrieb:
>The answer is "yes, you can" in this simple case. If the object
expects a reference to a base class, however, you have undefined
behavior (and I've encountered cases where it doesn't work),
since conversion to base is also undefined behavior.

Wait a second. What's that? Has the following undefined behaviour?

struct Foo {
private:
//..lots of member variables needing initialisation
string name;
Bar whatever;
protected:
void run();
};

struct Runner : Foo
{
Runner();
~Runner();
boost::thread myThread;
};

Runner::Runner()
: Foo()
, myThread(bind(&Foo::run, this))
{}
Runner::~Runner()
{
myThread.interrupt();
myThread.join();
}

Maybe this doesn't actually force the conversion of "this" to "Foo*",
but it's an example of what I currently need in some code. I just want
to know some rules about this. So when does it become dangerous?
See 12.7/2. I can't claim full understanding of it, but it seems to say
that since in your code the construction of 'Foo' has completed by the
time 'myThread' is initialised by 'bind', it's OK. Conversion of 'this'
into 'Foo' would have undefined behaviour in this case:

class Foo;
class Bar {
public:
Bar(Foo*); // needs a pointer to Foo
};

class Fubar : public Bar, public Foo {
public:
Fubar() : Bar(this), Foo() {}
};

Note, that the Bar subobject is initialised before the construction of
the 'Foo' subobject begins.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jun 27 '08 #4
Hi!

Victor Bazarov schrieb:
Note, that the Bar subobject is initialised before the construction of
the 'Foo' subobject begins.
Ok. That's fine.

However James seemed to say you cannot cast "*this" into a base class
reference:

struct Base {};
struct HoldBase {
HoldBase(Base&);
};

struct Derived : Base {
Derived()
: Base(), hold(*this)
{}
HoldBase hold;
};

This transforms "*this" into a base class reference during
initialization. I interpreted James posting this way and concluded the
above must be invalid/undefined behaviour. And this seems rather odd,
don't you think?

Frank
Jun 27 '08 #5
On Jun 7, 1:13 am, Frank Birbacher <bloodymir.c...@gmx.netwrote:
Victor Bazarov schrieb:
Note, that the Bar subobject is initialised before the
construction of the 'Foo' subobject begins.
However James seemed to say you cannot cast "*this" into a
base class reference:
struct Base {};
struct HoldBase {
HoldBase(Base&);
};
struct Derived : Base {
Derived()
: Base(), hold(*this)
{}
HoldBase hold;
};
This transforms "*this" into a base class reference during
initialization. I interpreted James posting this way and
concluded the above must be invalid/undefined behaviour. And
this seems rather odd, don't you think?
It is undefined behavior, and I think it rather odd, too. The
reason I know it's undefined behavior, however, is that I ran
into an actual case where it didn't work, went to write up a
compiler bug report, and when trying to find where the standard
said it had to work, found just the opposite.

One way around it is to use a wrapper class which returns the
pointer---you can't convert the pointer, but you can call member
funtions on fully constructed sub-objects, so something like:

template< typename Base >
struct BaseWrapper
{
Base object ;
Base* ptr() ;
Base& ref() ;
} ;

struct Derived : BaseWrapper< Base >
: hold( ref() )
{
} ;

Although useful in some specific cases (I use it when deriving
from both a specific streambuf and istream or ostream), it is
awkward and overly complex in the general case. And if the
compiler is required to get its pointer conversions correct in
this case, why can't it do so in the other case?

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Jun 27 '08 #6
Hi!

James Kanze schrieb:
It is undefined behavior, and I think it rather odd, too. The
reason I know it's undefined behavior, however, is that I ran
into an actual case where it didn't work, went to write up a
compiler bug report, and when trying to find where the standard
said it had to work, found just the opposite.
Eeew. That's bad!
One way around it is to use a wrapper class which returns the
pointer---you can't convert the pointer, but you can call member
funtions on fully constructed sub-objects, so something like:
Or like:

struct Foo
{
//...here reguar definition
protected:
Foo* ptr() { return this; }
Foo* ref() { return *this; }
};

struct Dev : Foo
{
Dev();
Foo& useless;
};

Dev::Dev()
: Foo(), useless(Foo::ref())
{}

Would that be ok?

I call this a serious defect in the standard. Like you said, you didn't
expect undefined behaviour here anywhere. The conversion is simple to do
because it is needed for calling base class functions anyway. The above
ptr() and ref() methods show an easy implementation and proof this can
be done easily. Not specifying behaviour for conversions here is just a
dangerous pitfall!

Any chance this could be fixed in C++0x?

Frank
Jun 27 '08 #7
Hi!

James Kanze schrieb:
That's boost::bind, right. A template. So the function will
adopt to the type of this, and no conversion will be necessary.
Actually a conversion is eventually necessary: in calling the base class
run() method. If "target" was a pointer to the derived class, would
target ->* (&Base::run)();
include an undefined conversion? This conversion would take place in a
different thread but because of this might as well be done still during
initialization of Derived.
This is a problem with a lot of home built thread classes,
which, even worse, will offen convert the derived this to a
void* (legal, but...), only to convert the void* to Base* (and
not Derived*) in the start up routine.
Woah, bad bad bad. No more torture using void pointers please. ;)
The problem here is elsewhere:
Right, design could be better. I'm still working on it. It's a local
definition for instantiating a static variable which is used as a
singleton. It has had more problems before I refactored it to use boost
thread.

Frank
Jun 27 '08 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: Sören | last post by:
Hi, I'd like advise on passing ownership of an iostream. The idea is that my factory class/function should open a file, read enough to detect file type (eg which soundfile format), then...
25
by: Victor Bazarov | last post by:
In the project I'm maintaining I've seen two distinct techniques used for returning an object from a function. One is AType function(AType const& arg) { AType retval(arg); // or default...
13
by: Abe Frohnman | last post by:
Hello all, I'm passing a reference to a class into the constructor of a form, like so: public MyForm(int count, ref Area myArea) {...} How can I use myArea outside the constructor? Should I...
7
by: Ken Allen | last post by:
I have a .net client/server application using remoting, and I cannot get the custom exception class to pass from the server to the client. The custom exception is derived from ApplicationException...
3
by: lavu | last post by:
How would I pass parameters from the main form to my subform at load time. I use Activator.CreateInstance to create the subform. Thanks in advance. Ps: I tried googling for this but found no...
4
by: ingoweiss | last post by:
Hi, I am having trouble passing parameters of a Javascript subclass constructor through to it's superclass constructor. I am trying all sorts of things, including the below, but nothing...
2
by: PSN | last post by:
Hi all .. can any one please explain the output of the following code .. class A { public: int a1; int a2; A(int a1, int a2) { cout << "i am in AAA" << endl;
4
by: nickcleary1 | last post by:
I need to pass 4 integers between two forms but am having trouble passing more than one.I am hoping to use the contructor approach as i need the variables straight away Any help would be great ...
12
by: dave_dp | last post by:
Hi, I have just started learning C++ language.. I've read much even tried to understand the way standard says but still can't get the grasp of that concept. When parameters are passed/returned...
6
by: Sergey Poberezovskiy | last post by:
I have the following code in C# that I have trouble converting to VB(2.0): private delegate void openDialog(); private void openWindowsDialog(openDialog open) { Thread thread = new Thread(new...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.