开发者

Mysterious reference to empty constructor

Here's my header file Normal.h:

#ifndef NORMAL_H
#define NORMAL_H

#include "Vector3.h"

class Normal
{
public:
   Vector3 pos;
   Vector3 direction;

   Normal(Vector3, Vector3);
};

#endif

Here's the cpp file Normal.cpp:

开发者_StackOverflow
#include "Normal.h"
#include "Vector3.h"

Normal::Normal(Vector3 pos, Vector3 direction)
{
   this->pos = pos;
   this->direction = direction;
}

They are referencing a Vector3 class which does not have a constructor that takes no arguments. The only constructor specified takes 3 ints.

But I get an error when I try to run a test:

g++ Normal.cpp -o NormalTest.cpp 
/usr/lib/gcc/i486-linux-gnu/4.4.3/../../../../lib/crt1.o: In function `_start':
(.text+0x18): undefined reference to `main'
/tmp/ccxgbatN.o: In function `Normal::Normal(Vector3, Vector3)':
Normal.cpp:(.text+0xd): undefined reference to `Vector3::Vector3()'

I don't understand the error that says I have an undefined reference to 'Vector3::Vector3()' It looks like it's referring to this line: Normal::Normal(Vector3 pos, Vector3 direction)

I'm not fluent in C++, so any help would be appreciated.


This is not an uncommon C++ issue.

To fix it try

Normal::Normal(Vector3 pos, Vector3 direction): pos(pos), direction(direction)
{
}

The reason is that the way you defined your constructor, C++ says:

  1. Create a Normal object whose fields are initialized to their default values
  2. Then assign the fields.

But what are the default values of pos and direction? They are found by calling the default constructor of Vector3... but none is defined! Hence the error.

The alternative version of the constructor, using initializers instead of assignment, works as follows:

  1. Create a Normal object initializing fields on the fly with the copy constructor for its fields.

Assuming you have a copy constructor for Vector3, you should be okay.

In general writing constructors with initializers instead of assignment statements is a good idea, for this very reason.


In the g++ command that you ran, the compiler first compiles and then creates an executable by linking all dependencies (which is Vector3 in the case of Normal).

So, assuming there is Vector3.cpp, you should be doing something like this

g++ Normal.cpp Vector3.cpp -o NormalTest

or

g++ -c Normal.cpp
g++ -c Vector3.cpp
g++ Normal.o Vector3.o -o NormalTest

Next, should and executable be created out of 1 or more .cpp files, then at least one of the files should contain a 'main' method. So, add a main method to either Normal.cpp or Vector3.cpp to get rid of the "undefined reference to Main" error.


  1. You don't define a `main` function anywhere, the entry point, the function that calls everything else.
  2. Your invocation of the compiler, `g++ Normal.cpp -o NormalTest.cpp`, tells it to compile `Normal.cpp` and produce an executable (which it is to name `NormalTest.cpp`, which is wrong in at least two ways), but it can't because `Normal.cpp` in particular has no `main` function.
  3. Your `Vector3` class has a constructor that takes three arguments. Ordinarily the compiler will provide a default constructor (i.e. one that takes no arguments) for any class you invent, but if you define a constructor that does take arguments, then the compiler will not provide a default constructor. (This is a part of the C++ language, not a compiler issue.) If you don't define a constructor for `Vector3` that takes no arguments, then you must design your `Normal` constructor to construct the member `Vector3`'s with the constructor you have provided.
  4. Start with HelloWorld. Always start with HelloWorld.


You may want to consider storing pointers rather than copying objects as you are doing now. What your constructor is implicitly trying to do is to construct two empty Vector3's and then to copy the contents of the arguments (pos, direction) into those empty Vector3's that are the member variables of Normal.

These members are embedded objects, not pointers.

The implicit calls to the empty constructor Vector3() are caused by the existence of these embedded objects.

It's more typical to store pointers, so you might declare something like:

class Normal
{
public:
   Vector3 *pos;
   Vector3 *direction;

   Normal(Vector3*, Vector3*);
};

but if you insist on embedding the objects, I think there is a syntax to call the Vector3 constructor from the Normal constructor. It's like this:

Normal::Normal(Vector3 p, Vector3 dir) : pos(p), direction(dir) { }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜