Загадочная ссылка на пустой конструктор - PullRequest
0 голосов
/ 15 сентября 2011

Вот мой заголовочный файл 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 ()

Я не владею C ++, поэтому любая помощь будет признательна.

Ответы [ 4 ]

3 голосов
/ 15 сентября 2011

Это не редкая проблема C ++.

Чтобы исправить это, попробуйте

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

Причина в том, что, как вы определили ваш конструктор, C ++ говорит:

  1. Создание объекта Normal, поля которого инициализируются в значения по умолчанию
  2. Затем назначить поля.

Но каковы значения по умолчанию pos и direction? Их можно найти, вызвав конструктор по умолчанию Vector3 ... но ни один не определен! Отсюда и ошибка.

Альтернативная версия конструктора, использующая инициализаторы вместо присваивания, работает следующим образом:

  1. Создание объекта Normal, инициализирующего поля на лету с помощью конструктора копирования для его полей.

Предполагая, что у вас есть конструктор копирования для Vector3, все будет в порядке.

В целом, по этой причине хорошей идеей является написание конструкторов с инициализаторами вместо операторов присваивания.

1 голос
/ 15 сентября 2011

В команде g ++, которую вы выполнили, компилятор сначала компилирует, а затем создает исполняемый файл, связывая все зависимости (например, Vector3 в случае Normal).

Итак, предполагая, что есть 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.Итак, добавьте метод main в Normal.cpp или Vector3.cpp, чтобы избавиться от ошибки «неопределенная ссылка на Main».

0 голосов
/ 15 сентября 2011
  1. Вы нигде не определяете функцию main, точку входа, функцию, которая вызывает все остальное.
  2. Ваш вызов компилятора `g ++ Normal.cpp -o NormalTest.cpp` заставляет его скомпилировать` Normal.cpp` и создать исполняемый файл (который он должен называть NormalTest.cpp, что неверно в по крайней мере, двумя способами), но это невозможно, потому что `Normal.cpp`, в частности, не имеет функции` main`.
  3. Ваш класс `Vector3` имеет конструктор, который принимает три аргумента. Обычно компилятор предоставляет конструктор по умолчанию (т.е. тот, который не принимает аргументов) для любого изобретенного вами класса, , но , если вы определяете конструктор, который принимает аргументы, то компилятор будет не предоставляет конструктор по умолчанию. (Это часть языка C ++, а не проблема компилятора.) Если вы не определяете конструктор для `Vector3`, который не принимает аргументов, то вы должны сконструировать конструктор` Normal`, чтобы создать член `Vector3` ' с конструктором вы предоставили .
  4. Начните с HelloWorld. Всегда начинайте с HelloWorld.
0 голосов
/ 15 сентября 2011

Возможно, вы захотите хранить указатели, а не копировать объекты, как вы это делаете сейчас.То, что ваш конструктор неявно пытается сделать, - это создать два пустых вектора Vector3 и затем скопировать содержимое аргументов (pos, direction) в те пустые векторы Vector3, которые являются переменными-членами Normal.

Эти члены встроеныобъекты, а не указатели.

Неявные вызовы пустого конструктора Vector3 () вызваны существованием этих встроенных объектов.

Более типично хранить указатели, поэтому вы можете объявить что-то вроде:

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

   Normal(Vector3*, Vector3*);
};

но если вы настаиваете на встраивании объектов, я думаю, что есть синтаксис для вызова конструктора Vector3 из конструктора Normal.Это так:

Normal::Normal(Vector3 p, Vector3 dir) : pos(p), direction(dir) { }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...