Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 19, средняя оценка - 4.95
jemper
0 / 0 / 0
Регистрация: 15.01.2010
Сообщений: 6
#1

[linker error] undefined reference to 'vtable for Car' - C++

15.01.2010, 18:16. Просмотров 2379. Ответов 13
Метки нет (Все метки)

доброго времени вам. помогите, пожалуйста, с задачей разобраться. хочу сделать пример на паттерн "абстрактная фабрика". фабрика собирает афтомобили.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include <cstdlib>
#include <iostream>
#include <new>
#include <cstring>
 
using namespace std;
 
 
class Engine 
{ 
public: 
  virtual void setSpeedLimit(int kmph); 
  virtual void addOil(float amount); 
  
}; 
class Wheel 
{ 
  float mRadius; 
public: 
  Wheel(float radius) { mRadius = radius; } 
  virtual float getRadius() const {return mRadius;} 
}; 
 
 
class Car 
{ 
public: 
  virtual const char* getName() = 0; 
  virtual void setEngine(Engine* engine); 
  virtual void setWheels(Wheel* FR, Wheel* FL, Wheel* BR, Wheel* BL);
 // virtual void setFrontWheels(Wheel* FR, Wheel* FL); 
 // virtual void setBackWheels(Wheel* BR, Wheel* BL); 
 
};
class AbstractCarFactory  //создаем абстрактный класс, с единственным предназначением- быть 
                         //родителем для других классов.
{ 
public: 
  virtual Car* createCar() = 0;
  virtual Engine* createEngine() = 0;
  virtual Wheel* createWheel() = 0;
};
class CarBMW5 : public Car 
{ 
public: 
   const char* getName() {return "BMW5";} 
   void setEngine(Engine* engine) {engine->setSpeedLimit(100); engine->addOil(12.3); } 
   void setWheels(Wheel* FR, Wheel* FL, Wheel* BR, Wheel* BL) {cout<< "колеса";}
};
 
class BMW5CarFactory : public AbstractCarFactory 
{ 
 public: 
  virtual Car* createCar() { return new CarBMW5(); } 
  virtual Engine* createEngine() {return new Engine();} 
  virtual Wheel* createWheel() {return new Wheel(16);} 
 }; 
 
Car* createCar(AbstractCarFactory* carFactory) 
{ 
  Car* car = carFactory->createCar(); 
  Engine* engine = carFactory->createEngine(); 
  car->setEngine(engine); 
  car->setWheels(carFactory->createWheel(), carFactory->createWheel(), carFactory->createWheel(), carFactory->createWheel()); 
  //  код для "сборки" готового автомобиля из частей 
  return car; 
}
 
 
int main(int argc, char *argv[])
{
 CarBMW5 a;  // при попытке создания объекта класса выдает ошибки во время компиляции. если  строку закомментировать - ошибок не выдает.
// BMW5CarFactory b;  
    system("PAUSE");
    return EXIT_SUCCESS;
}
ошибки:
[linker error] undefined reference to 'vtable for Car'
ld returned 1 exit status
C:\Dev-Cpp\Makefile.win [Build Error] [project1.exe] Error 1
если раскомментировать строку "// BMW5CarFactory b; " то добавляет к этим ошибкам еще такую:
[Linker error] undefined reference to `vtable for Engine'
ранних версий компилятора не было, да и других компиляторов вроде нету на компе..
какая может быть причина, подскажите, пожалуйста)
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
15.01.2010, 18:16
Здравствуйте! Я подобрал для вас темы с ответами на вопрос [linker error] undefined reference to 'vtable for Car' (C++):

Странная ошибка: [Linker error] undefined reference to `__dyn_tls_init_callback' [Linker error] undefined reference to ld returned 1 exit status - C++
Здравствуйте. Вот недавно начал изучать книгу &quot;С++ для чайников&quot; Стефан Р. Девис 4-е издание. И напоролся на кучу ошибок) Но смог все...

[Linker Error] undefined reference to - C++
Вызываю так функцию в main'e: #include &lt;cstdlib&gt; #include &lt;iostream&gt; #include &lt;iomanip&gt; #include &quot;matrix.h&quot; using...

[Linker error] undefined reference to 'r' - C++
Помогите решить вышеописанную проблему, на переменную s так же ругаеться! #include &lt;stdio.h&gt; #include &lt;stdlib.h&gt; #include &lt;conio.h&gt; ...

[Linker error] undefined reference to - C++
#include&lt;string.h&gt; #include&lt;stdlib.h&gt; #include&lt;conio.h&gt; #include&lt;stdio.h&gt; #include &lt;math.h&gt; #include&lt;fstream&gt; ...

[Linker Error] undefined reference to `__dyn_tls_init_callback' - C++
#include &lt;stdio.h&gt; #include &lt;conio.h&gt; int SumDigits (int N) { int d, sum = 0; while ( N != 0 ) ...

[Linker error] undefined reference to __cpu_features_init - C++
Вот наглядное пособие: ... А что он говорит и что делать, чтобы прога заработала?

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
M128K145
Эксперт С++
8288 / 3508 / 143
Регистрация: 03.07.2009
Сообщений: 10,706
15.01.2010, 19:38 #2
C++
1
CarBMW5 *a;
0
jemper
0 / 0 / 0
Регистрация: 15.01.2010
Сообщений: 6
16.01.2010, 09:12  [ТС] #3
да, я так делал уже. при этом все вроде нормально, но программа падает на выполнении, например, такой команды:
C++
1
а->getName();
и мне интересно, почему нельзя непосредственно создать объект класса CarBMW5? зачем обязательно создавать указатель на объект? в чем ошибка?
0
Evg
Эксперт CАвтор FAQ
17826 / 6036 / 388
Регистрация: 30.03.2009
Сообщений: 16,567
Записей в блоге: 26
16.01.2010, 11:34 #4
jemper, это у тебя задание в институте или ты для для себя изучаешь?
0
jemper
0 / 0 / 0
Регистрация: 15.01.2010
Сообщений: 6
16.01.2010, 11:38  [ТС] #5
вообще не понимаю, что это слово "vtable" означает и откуда оно взялось

Добавлено через 1 минуту
да самому разобраться нужно.. но и к институту имеет отношение
0
ISergey
Maniac
Эксперт С++
1374 / 885 / 52
Регистрация: 02.01.2009
Сообщений: 2,658
Записей в блоге: 1
16.01.2010, 12:00 #6
http://ru.wikipedia.org/wiki/Абстрак...проектирования)
0
Evg
Эксперт CАвтор FAQ
17826 / 6036 / 388
Регистрация: 30.03.2009
Сообщений: 16,567
Записей в блоге: 26
16.01.2010, 12:49 #7
Цитата Сообщение от jemper Посмотреть сообщение
вообще не понимаю, что это слово "vtable" означает и откуда оно взялось
В отличие от Си, язык Си++ является высокоуровневым. Т.е. ты пишешь в исходнике чего-то, а в процессе построения кода компилятор дополнительно рожает ещё целую кучу кода. В данном случае компилятор строит дополнительные таблицы виртуальных функций (слово vtable берётся оттуда)

Цитата Сообщение от jemper Посмотреть сообщение
да самому разобраться нужно.. но и к институту имеет отношение
Я просто спросил к тому, что у тебя классы концептуально неправильно реализованы. Вообще для классов есть понятия "свойство" и "метод". Свойство - это то, что можно хранить в виде данных. Например, если есть класс "фигура круг", то "радиус" - это свойство, ибо его можно хранить в виде данных. А вот "нарисовать" это уже метод, поскольку он требует каких-то действий и его нельзя хранить в виде данных (в нормальном случае)

В твоём случае название машины выполнено в виде метода, хотя это данное в чистом виде. Идеологически правильным было бы сделать так:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>
 
class Car 
{ 
private:
  // Название машины. Модификатор const по сути дела означает то, что
  // это поле можно изменить только при создании объекта в конструкторе,
  // после чего это поле модифицировать уже нельзя. Название машины - это
  // такая вещь, которая даётся машине один раз и уже не меняется.
  // Модификатор const дополнительно спасёт нас от внутренних ошибок
  // и при попытке изменить это поле компилятор выругается
  std::string const m_Name;
 
public: 
  // В конструкторе записываем название
  Car (const std::string &name) : m_Name (name) { }
 
  // Метод getName НЕ должен быть виртуальным, т.к. всё разнообразие
  // наследников класса будет записывать имя машины в поле m_Name,
  // при этом метод остаётся единым для всех. Т.е. различие идёт НЕ
  // в реализации метода, а в хранении данных
  const std::string& getName() const { return m_Name; }
};
 
class CarBMW : public Car
{
public:
  // Из нашего конструктора вызываем конструктор базового класса, чтобы
  // задать ему свойство m_Name
  CarBMW () : Car ("BMW") { }
};
 
class CarAudi : public Car
{
public:
  // Аналогично
  CarAudi () : Car ("Audi") { }
};
 
int
main (void)
{
  CarBMW car1;
  CarAudi car2;
 
  std::cout << car1.getName() << endl;
  std::cout << car2.getName() << endl;
}
Колёса должны быть такими же данными. Но в случае с колёсами ситуация немного другая. За время жизни колёса могут меняться (но название остаётся одним и тем же). Поэтому колёса должны быть выполнены так, чтобы их можно было заменять

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Car
{
  ...
private:
  Wheel *m_W1, *m_W2, *m_W3, *m_W4;
public:
  setWheels (Wheel *w1, Wheel *w2, Wheel *w3, Wheel *w4)
  {
    m_W1 = w1;
    m_W2 = w2;
    m_W3 = w3;
    m_W4 = w4;
  }
  getWheel1 () { return m_W1; }
  getWheel2 () { return m_W2; }
  getWheel3 () { return m_W3; }
  getWheel4 () { return m_W4; }
}
В итоге в конечном счёте получается, что на данном уровне тебе виртуальные функции не нужны

Добавлено через 2 минуты
Да, использование string'ов вместо char*, использование модификаторов const, передаче параметров по ссылке (через &) может тебе показаться несколько непонятным. В приницпе, можно переписать и без этого, но если нужно для себя, то лучше приучай себя сразу к тому, что делать по-человечески
1
zim22
depict1
276 / 141 / 2
Регистрация: 11.07.2009
Сообщений: 606
16.01.2010, 14:01 #8
Цитата Сообщение от jemper Посмотреть сообщение
да и других компиляторов вроде нету на компе..
онлайн-компилятор
codepad.org
0
Evg
Эксперт CАвтор FAQ
17826 / 6036 / 388
Регистрация: 30.03.2009
Сообщений: 16,567
Записей в блоге: 26
16.01.2010, 14:07 #9
Кстати, в моём примере колёса в машине хранились по указателю, при этом колёса создавались ЗА пределами класса машины. Это есть опасная конструкция, т.к. в месте создания можно ошибиться и удалить колёса, в результате чего в машине окажутся указатели на удалённые объекты. Более правильно колёса хранить по значению.

По указателю можно хранить только то, что создаётся внутри класса (и, соотвественно, будет удалено внутри класса). Эти указатели по возможности наружу не выдавать, чтобы их кто-то случайно не удалил. Для маленьких программ такие проблемы ищутся быстро, но в больших проектах можно искать очень долго
0
zim22
depict1
276 / 141 / 2
Регистрация: 11.07.2009
Сообщений: 606
16.01.2010, 14:11 #10
Цитата Сообщение от Evg Посмотреть сообщение
Более правильно колёса хранить по значению.
нет "более правильного" и "менее правильного". всё зависит от ситуации.

если колёса должны будут существовать после того, как машина будет уничтожена - класс "машина" просто берёт их в аренду, иначе - время жизни этих объектов должно совпадать.
0
jemper
0 / 0 / 0
Регистрация: 15.01.2010
Сообщений: 6
16.01.2010, 14:22  [ТС] #11
большое спасибо за ответы, сейчас сижу разбираюсь...
0
zim22
depict1
276 / 141 / 2
Регистрация: 11.07.2009
Сообщений: 606
16.01.2010, 14:37 #12
Цитата Сообщение от jemper Посмотреть сообщение
сейчас сижу разбираюсь...
здесь хорошо паттерны описаны
0
Evg
Эксперт CАвтор FAQ
17826 / 6036 / 388
Регистрация: 30.03.2009
Сообщений: 16,567
Записей в блоге: 26
16.01.2010, 16:23 #13
Цитата Сообщение от zim22 Посмотреть сообщение
нет "более правильного" и "менее правильного". всё зависит от ситуации
"Более правильно" или "менее правильно" относилось скорее к технике (стилю) программирования, чем к ООП. С ходу могу написатьпример, который при указанном методе хранения начнёт косячить, хотя идеологически вроде бы всё правильно. Когда один человек пишет одну маленькую программу - соображения о правильности такие. Когда тысяча человек пишут программу, исходники которой исчисляются сотнями мегабайт, соображения будут совсем другие. Причём я очень чётко понимаю, что начинающему это различие объяснить очень сложно (потому как когда-то мне тоже объясняли, но я считал эти объяснения неправильными)
0
Evg
Эксперт CАвтор FAQ
17826 / 6036 / 388
Регистрация: 30.03.2009
Сообщений: 16,567
Записей в блоге: 26
24.12.2011, 12:43 #14
Для истории более грамотный пример на реализацию наследования:
Создать класс "Студент" и классы "Бюджетный студент" и "Коммерческий студент"
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
24.12.2011, 12:43
Привет! Вот еще темы с ответами:

[Linker Error] undefined reference to `instructions()' - C++
Dev c++ #include &lt;iostream&gt; using namespace std; void instructions(); int main() { instructions(); return 0;} void...

Ошибка [Linker error] undefined reference to `__dyn_tls_init_callback' - C++
Вот такие ошибки появляются : Ошибка undefined reference to `__dyn_tls_init_callback' undefined reference to...

Выдает ошибку [Linker error] undefined reference to `WinMain@16' - C++
Собственно проблема в сабже - выдает gcc.exe &quot;J:\Курсовая БД\Курсовая .c&quot; -o &quot;J:\Курсовая БД\Курсовая .exe&quot; ...

undefined reference to `vtable for - C++
Вылетает эта ошибка при компиляции вот этого класса: class BrassPlus : public AcctABC { private: double maxLoan; double...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
24.12.2011, 12:43
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru