views:

225

answers:

4

In C++, is it possible to call a function of an instance before the constructor of that instance completes?

e.g. if A's constructor instantiates B and B's constructor calls one of A's functions.

+4  A: 

This is very possible

class A;
class B { 
public:
  B(A* pValue);
};

class A {
public:
  A() {
    B value(this);
  }
  void SomeMethod() {}
};

B::B(A* pValue) {
  pValue->SomeMethod();
}
JaredPar
+11  A: 

Yes, that's possible. However, you are responsible that the function invoked won't try to access any sub-objects which didn't have their constructor called. Usually this is quite error-prone, which is why it should be avoided.

sbi
Included in this (but deserving of emphasis) is that you should not call virtual member functions from your constructor, at least, not without understanding what will happen. As any derived class has not yet been fully constructed, calling an overridden virtual function in a base class constructor will call the base-class implementation of that function (and if the base-class function is pure virtual, you will get a run time error). So, best not to call _any_ virtual functions in the constructor.
Matthew Hall
@Matthew: Indeed. Thank you for that valuable addition!
sbi
+2  A: 

It's possible and sometimes practically necessary (although it amplifies the ability to level a city block inadvertently). For example, in C++98, instead of defining an artificial base class for common initialization, in C++98 one often see that done by an init function called from each constructor. I'm not talking about two-phase construction, which is just Evil, but about factoring out common initialization.

C++0x provides constructor forwarding which will help to alleviate the problem.

For the in-practice it is Dangerous, one has to be extra careful about what's initialized and not. And for the purely formal there is some unnecessarily vague wording in the standard which can be construed as if the object doesn't really exist until a constructor has completed successfully. However, since that interpretation would make it UB to use e.g. an init function to factor out common initialization, which is a common practice, it can just be disregarded.

Cheers & hth.,

Alf P. Steinbach
A: 

why would you wanna do that? No, It can not be done as you need to have an object as one of its parameter(s). C++ member function implementation and C function are different things.

c++ code

class foo
{
    int data;
    void DoSomething()
    {
        data++;
    }
};


int main()
{
    foo a;              //an object
    a.data = 0;         //set the data member to 0
    a.DoSomething();    //the object is doing something with itself and is using 'data'
}

Here is a simple way how to do it C.

typedef void (*pDoSomething) ();
typedef struct __foo
{
    int data;
    pDoSomething ds;    //<--pointer to DoSomething function
}foo;

void DoSomething(foo* this)
{
    this->data++;   //<-- C++ compiler won't compile this as C++ compiler uses 'this' as one of its keywords.
}

int main()
{
    foo a;
    a.ds = DoSomething; // you have to set the function.
    a.data = 0;
    a.ds(&a);       //this is the same as C++ a.DoSomething code above.
}

Finally, the answer to your question is the code below.

void DoSomething(foo* this);
int main()
{
    DoSomething( ?? );  //WHAT!?? We need to pass something here.
}

See, you need an object to pass to it. The answer is no.

renai
You come almost three hours after Jared has shown how this could happen and in your second sentence you blurt out that this cannot be done?! I'm amazed.
sbi