views:

148

answers:

3

Here my code snippet:

class Request
{
public:
 Request(void);
………..
}

Request::Request(void)
{
 qDebug()<<"Request: "<<"Hello World";
}


class LoginRequest :public Request
{
public:
 LoginRequest(void);
 LoginRequest(QDomDocument);
……………
}

LoginRequest::LoginRequest(void)
{
 qDebug()<<"LoginRequest: "<<"Hello World";
 requestType=LOGIN;
 requestId=-1;   
}

LoginRequest::LoginRequest(QDomDocument doc){
 qDebug()<<"LoginRequest: "<<"Hello World with QDomDocument";
 LoginRequest::LoginRequest();       
 xmlDoc_=doc;         
}

When call constructor of Overrided LoginRequest

LoginRequest *test=new LoginRequest(doc);

I came up with this result:

Request:  Hello World
LoginRequest:  Hello World with QDomDocument
Request:  Hello World
LoginRequest:  Hello World

Obviously both constructor of LoginRequest called REquest constructor.

Is there any way to cape with this situation?

I can construct another function that does the job I want to do and have both constructors call that function. But I wonder is there any solution?

Edit: http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.3

+1  A: 

Yes, your solution to use a function and call it from both constructors is a good one (oder maybe better: make a class hierarchy Request - LoginRequest - LoginRequestWithDoc).

C# provides what you need/tried to achieve but not C++: a ctor of a class call another ctor of the same class.

class LoginRequest
{
  public LoginRequest()
  {
    // ...
  }

  public LoginRequest( Document doc )
    : this()   // <<< order of execution: Request() -> LoginRequest()
               //                         -> LoginRequest( doc )
  {
    // ...
  }
}
ur
Although it will be in C++0x.
Mike Seymour
+6  A: 

The code is not doing what you probably think it is doing. The line:

 LoginRequest::LoginRequest();     

constructs a temporary object which is immediately destroyed. as others have suggested, you can put duplicate code in a private function, but this has a lot of issues - specifically, such a function can only perform assignment, not initialisation, and many classes do not support assignment. A somewhat better solution is to implement a single constructor with a default argument:

class LoginRequest {
   ....
   LoginRequest( QDomDocument d = DefaultDoc() );
};
anon
Why can not it initialize?
metdos
@metdos Because it is (presumably) called after initialisation takes place. I don't understand your second comment.
anon
@metdos Sorry - still don't understand. It's a variable, you use it like you use other variables.
anon
@Neil Butterworth Sorry, Now I see what you mean. Thanks.
metdos
+1  A: 

I can construct another function that does the job I want to do and have both constructors call that function. But I wonder is there any solution?

Yes, there is:

First, move the code for initialization into an initialization list. It is more efficient and good coding practice.

Second, Any code that's common to both constructors and not an initialization (that is, it cannot be put in an initialization list) should be moved to a common private function and called from both constructors.

Usually it is not good to call a constructor from another constructor as - depending on what the compiler is doing you may have strange/undefined behavior (in this case the base class gets initialized twice).

utnapistim
No, the base class is not initrialised twice. A completely different base class instance is created.
anon