2

I am cross-compiling a project from MSVC2010 to GCC 4.7 .Each place where I call base class constructor like this :

 FPSCamera::FPSCamera(CameraType camType, float fov, int viewportW, int viewportH, float nearPlane, float farPlane)
{
    Camera3D::Camera3D( camType,  fov,  viewportW,  viewportH,  nearPlane,  farPlane);

}

I am getting in GCC :

CANNOT CALL CONSTRUCTOR DIRECTLY

MSVC doesn't complain ... This way the error is fixed:

FPSCamera::FPSCamera(CameraType camType, float fov, int viewportW, int viewportH, float nearPlane, float farPlane)

       :Camera3D( camType,  fov,  viewportW,  viewportH,  nearPlane,  farPlane);

{

}

Why?

juanchopanza
  • 223,364
  • 34
  • 402
  • 480
Michael IV
  • 11,016
  • 12
  • 92
  • 223
  • 1
    This link has the answer: http://stackoverflow.com/questions/120876/c-superclass-constructor-calling-rules – Jimbo May 19 '13 at 09:35
  • but why MSVC doesn't enforce it on compilation ? – Michael IV May 19 '13 at 09:38
  • That I don't know. Once you're in the constructor of your derived class the base class has already been created (so has the derived class). That's why you must call the base class constructor from the initializer list. Why MSVC isn't complaining I'm not sure. You defo need to call base class constructor from initializer list though... – Jimbo May 19 '13 at 09:40

2 Answers2

8

This is a bug in VC++ 2010 - constructors are nameless special member functions and cannot be called directly. In this case the default constructor of the base class is called fist then the parameterized constructor of the base class is called. The reason you may not have noticed any problems with this is the this pointer is different between both calls to the base constructors. Two separate objects appear to be getting constructed but only one is being destroyed. Depending on what resources are acquired by the base class there may be some leaks or bugs that you are not aware of yet.

The example below shows what is happening during construction.

#include <iostream>

class Base
{
public:
    Base()
    {
        std::cout << "Base default ctor. this = " << this << std::endl;
    }
    Base(int)
    {
        std::cout << "Base parameterized ctor. this = " << this << std::endl;
    }
};

class Derived : public Base
{
public:
    Derived()
    {
        std::cout << "Inside derived ctor." << std::endl;
        Base::Base(1);
        std::cout << "Leaving derived ctor" << std::endl;
    }
};



int main()
{
    Derived();
    return 0;
}

Results:

Base default ctor. this = 00000000002FF6F0
Inside derived ctor.
Base parameterized ctor. this = 00000000002FF6B0
Leaving derived ctor

[Note: Microsoft has no plans of fixing this problem any time soon]

Captain Obvlious
  • 19,754
  • 5
  • 44
  • 74
  • Thanks a lot. Now it is clear to me.Pity that MSVC compilers are forgiving on this especially when the user is C++ Noob :) – Michael IV May 19 '13 at 09:57
  • I thought I had a reference to the extension docs for this but I'm coming up blank. It's possible I saw it in a bug report so I'm searching now just to make sure it's included if necessary. Either way it's ugly and nasty and shouldn't exist. – Captain Obvlious May 19 '13 at 10:01
1

Posting as an answer rather than comment...

Not sure why MSVC isn't complaining but you must initialise base class in the derived class constructor's initialiser list.

The reason for this is that when you are in the body of the class constructor you class, incluuding base clases have already been constructed, so calling the base constructor from the function body doesn't make sense.

My guess is the MSVC is just treating this as a normal function call? It can't be constructing the base class, because it has already been constructed, so I presume it's treating it as a "normal" function call. So, although it doesn't construct the base class it might have the effect of doing some initialisation...

See also What are the rules for calling the superclass constructor?

Community
  • 1
  • 1
Jimbo
  • 4,352
  • 3
  • 27
  • 44