19

I've looked at a few other questions about this, but I don't see why a default constructor should even be called in my case. I could just provide a default constructor, but I want to understand why it is doing this and what it affects.

error C2512: 'CubeGeometry' : no appropriate default constructor available  

I have a class called ProxyPiece with a member variable of CubeGeometry.The constructor is supposed to take in a CubeGeometry and assign it to the member variable. Here is the header:

#pragma once
#include "CubeGeometry.h"

using namespace std;
class ProxyPiece
{
public:
    ProxyPiece(CubeGeometry& c);
    virtual ~ProxyPiece(void);
private:
    CubeGeometry cube;
};

and the source:

#include "StdAfx.h"
#include "ProxyPiece.h"

ProxyPiece::ProxyPiece(CubeGeometry& c)
{
    cube=c;
}


ProxyPiece::~ProxyPiece(void)
{
}

the header for cube geometry looks like this. It doesn't make sense to me to use a default constructor. Do I need it anyways?:

#pragma once
#include "Vector.h"
#include "Segment.h"
#include <vector>

using namespace std;

class CubeGeometry
{
public:
    CubeGeometry(Vector3 c, float l);

    virtual ~CubeGeometry(void);

    Segment* getSegments(){
        return segments;
    }

    Vector3* getCorners(){
        return corners;
    }

    float getLength(){
        return length;
    }

    void draw();

    Vector3 convertModelToTextureCoord (Vector3 modCoord) const;

    void setupCornersAndSegments();

private:
    //8 corners
    Vector3 corners[8];

    //and some segments
    Segment segments[12];

    Vector3 center;
    float length;
    float halfLength;
};
AAB
  • 674
  • 3
  • 14
  • 27

2 Answers2

39

Your default constructor is implicitly called here:

ProxyPiece::ProxyPiece(CubeGeometry& c)
{
    cube=c;
}

You want

ProxyPiece::ProxyPiece(CubeGeometry& c)
   :cube(c)
{
    
}

Otherwise your ctor is equivalent to

ProxyPiece::ProxyPiece(CubeGeometry& c)
    :cube() //default ctor called here!
{
    cube.operator=(c); //a function call on an already initialized object
}

The thing after the colon is called a member initialization list.

Incidentally, I would take the argument as const CubeGeometry& c instead of CubeGeomety& c if I were you.

Community
  • 1
  • 1
Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
  • 3
    To be even clearer, perhaps you could, in your "is the same as" snippet, change `cube = c;` to `cube.operator=(c);`. It would help explain that the assignment does not (from a language perspective) re-initialise `cube`. –  Mar 29 '13 at 19:33
  • So all default constructors of any member variables are called before the constructor to the containing class? (and yes I'll make it a const :) ) – AAB Mar 29 '13 at 19:36
  • 2
    @AABoucher: Yes. Although not *before* the constructor, but rather in the beginning of it. Ctor-init-list is part of the constructor call. But yes, once you've entered the *body* of your constructor, all the members are initialized - either explicitly in the ctor-init-list or implicitly. You can't *initialize* a member in the ctor body – Armen Tsirunyan Mar 29 '13 at 19:38
9

Member initialization occurs when the constructor begins. If you do not provide an initializer in the constructor's member initialization list, the member will be default constructed. If you want to copy constructor to be used to initialize the member cube, use the member initialization list:

ProxyPiece::ProxyPiece(CubeGeometry& c)
  : cube(c)
{ }

Everything following the colon is the initialization list. This simply says that cube should be initialized with c.

As you had it, the cube member was first default initialized and then c was copy assigned to it.

Joseph Mansfield
  • 108,238
  • 20
  • 242
  • 324