神秘引用空构造函数

时间:2011-09-15 01:16:38

标签: c++ compiler-errors

这是我的头文件Normal.h:

#ifndef NORMAL_H
#define NORMAL_H

#include "Vector3.h"

class Normal
{
public:
   Vector3 pos;
   Vector3 direction;

   Normal(Vector3, Vector3);
};

#endif

这是cpp文件Normal.cpp:

#include "Normal.h"
#include "Vector3.h"

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

它们引用了一个Vector3类,它没有不带参数的构造函数。唯一指定的构造函数需要3个整数。

但是当我尝试运行测试时出现错误:

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()'

我不明白错误说我对'Vector3 :: Vector3()'有一个未定义的引用看起来它指的是这一行:Normal::Normal(Vector3 pos, Vector3 direction)

我不熟悉C ++,所以任何帮助都会受到赞赏。

4 个答案:

答案 0 :(得分:3)

这不是一个不常见的C ++问题。

要修复它,请尝试

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

原因是你定义构造函数的方式,C ++说:

  1. 创建一个Normal对象,其字段初始化为默认值
  2. 然后分配字段。
  3. posdirection的默认值是多少?通过调用Vector3的默认构造函数找到它们...但没有定义!因此错误。

    构造函数的替代版本使用初始化程序而不是赋值,其工作方式如下:

    1. 创建一个Normal对象,使用其字段的复制构造函数动态初始化字段。
    2. 假设你有Vector3的复制构造函数,你应该没问题。

      一般来说,使用初始化程序而不是赋值语句编写构造函数是个好主意,因为这个原因。

答案 1 :(得分:1)

在您运行的g ++命令中,编译器首先编译然后通过链接所有依赖项(在Normal的情况下为Vector3)创建可执行文件。

所以,假设有Vector3.cpp,你应该做这样的事情

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

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

接下来,应该使用1个或多个.cpp文件创建和执行可执行文件,然后至少有一个文件应包含“main”方法。因此,在Normal.cpp或Vector3.cpp中添加一个main方法,以消除“对Main的未定义引用”错误。

答案 2 :(得分:0)

  1. 你没有在任何地方定义`main`函数,入口点,调用其他所有东西的函数。
  2. 您调用编译器`g ++ Normal.cpp -o NormalTest.cpp`,告诉它编译`Normal.cpp`并生成一个可执行文件(它命名为`NormalTest.cpp`,这至少有两种方法是错误的,但它不能,因为`Normal.cpp`特别没有'main`功能。
  3. 你的`Vector3`类有一个带三个参数的构造函数。通常,编译器将为您发明的任何类提供默认构造函数(即不带参数的构造函数),但是如果您定义 接受参数的构造函数,那么编译器将提供默认构造函数。 (这是C ++语言的一部分,而不是编译器问题。)如果你没有定义不带参数的`Vector3`的构造函数,那么你必须设计你的`Normal`构造函数来构造成员`Vector3`'使用提供的构造函数的s。
  4. 从HelloWorld开始。始终从HelloWorld开始。

答案 3 :(得分:-1)

您可能需要考虑存储指针而不是像现在这样复制对象。你的构造函数隐式尝试做的是构造两个空的Vector3,然后将参数的内容(pos,direction)复制到那些作为Normal的成员变量的空Vector3中。

这些成员是嵌入对象,而不是指针。

对空构造函数Vector3()的隐式调用是由这些嵌入对象的存在引起的。

存储指针更为典型,因此您可以声明如下内容:

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

   Normal(Vector3*, Vector3*);
};

但是如果你坚持嵌入对象,我认为有一种语法可以从Normal构造函数中调用Vector3构造函数。就像这样:

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