Автор Тема: Компилиране на програма?  (Прочетена 1881 пъти)

plamen_t

  • Напреднали
  • *****
  • Публикации: 170
    • Профил
Компилиране на програма?
« -: Dec 12, 2006, 18:12 »
Значи проблемът е следният.
Имам например следния хедър a.h
Примерен код
#ifndef A_H
#define A_H

class A
{
public:
   A(int);
   int get();

private:
   int x;
};

#endif


Имплементацията се намира в a.cpp
Примерен код
#include "a.h"
A::A(int a) : x(a)
{}

int A::get()
{
   return x;
}
И накрая един главена файл main.cpp
Примерен код
#include <iostream>
#include "a.h"

int main()
{
   A a(3);
   std::cout<<a.get();

   return 0;
}
Когато се опитам да я компилирам с
Примерен код
g++ -o main main.cpp
програмата се компилира, но линкера гърми с грешката
Примерен код
In function main:
Undefined reference to A::get()
Същото изкарва и за конструктора. Та въпросът ми е как мога да компилирам програма , която е разделена на няколко файла?
Активен

astronom

  • Напреднали
  • *****
  • Публикации: 254
    • Профил
Компилиране на програма?
« Отговор #1 -: Dec 12, 2006, 18:28 »
g++ -o a.o a.cpp
g++ -o main a.o main.cpp # Директно подаваш на линкера предварително компилирания обектен файл на класа.

Можеш и Makefile да си направиш.
Активен

Г. Д. Сотиров

dvasilev

  • Напреднали
  • *****
  • Публикации: 200
  • Distribution: Kubuntu, Debian
  • Window Manager: KDE
    • Профил
    • WWW
Компилиране на програма?
« Отговор #2 -: Dec 12, 2006, 18:31 »
В твоя случай пробвай с g++ -o main main.cpp a.cpp
Активен

plamen_t

  • Напреднали
  • *****
  • Публикации: 170
    • Профил
Компилиране на програма?
« Отговор #3 -: Dec 12, 2006, 18:59 »
@astronom

Като пробвам с g++ -o a.o a.cpp и линкера дава грешка
Цитат
In function `_start'
undefined reference to `main'


Btw как да си направя Makefile.

@dvasilev

10х. Така работи.
Активен

TheNightmare

  • Гост
Компилиране на програма?
« Отговор #4 -: Dec 12, 2006, 21:36 »
За най-лесно си сложи някоя среда от рода на Anjuta, Code::Blocks или KDevelop
Активен

tseso

  • Напреднали
  • *****
  • Публикации: 12
    • Профил
Компилиране на програма?
« Отговор #5 -: Dec 12, 2006, 23:57 »
#include "a.h"
A::A(int a) : x(a)
{}

int A::get()
{
  return x;
}

x(a) трябва да е конструктура на базовия клас, а в случая "А" е основен.

синтаксис на коструктор на производен клас:

клас::клас(аргументи...) : базов клас (аргументи)
{

}

Предложение:

A::A(int a)
{
  x=a;
}

int A::get()
{
  return x;
}
Активен

plamen_t

  • Напреднали
  • *****
  • Публикации: 170
    • Профил
Компилиране на програма?
« Отговор #6 -: Dec 13, 2006, 00:50 »
Конструкцията
Примерен код
A::A(int a) : x(a)
{}
си е напълно валидна и е еквивалентна на
Примерен код
A::A(int a)
{
   x=a;
}

В С++ основните типове като int ,char и т.н. могат да се разглеждата като обекти и съответно си имат конструктори. Също така
Цитат
синтаксис на коструктор на производен клас:

клас::клас(аргументи...) : базов клас (аргументи)
{

}
не е точно така, а по-скоро
Цитат
синтаксис на коструктор на производен клас:

клас::клас(аргументи...) : инициализиращ списък
{

}

И тъй като  x се явява като инстанция на класа int в класа А може да му извикаме конструктора в инициализиращия списък
Всъщност това е и единствения начин да инициализираме константна член-данна в класа
Примерен код
class A
{
.....
private:
   const int a;
};

Също така не е проблем да се използва int a(3) вместо int a=3 '<img'>



Активен

astronom

  • Напреднали
  • *****
  • Публикации: 254
    • Профил
Компилиране на програма?
« Отговор #7 -: Dec 13, 2006, 10:15 »
Цитат (plamen_t @ Дек. 12 2006,18:59)
@astronom
Като пробвам с g++ -o a.o a.cpp и линкера дава грешка
Цитат
In function `_start'
undefined reference to `main'


Да, защото съм забравил да сложа едно -c, за да компилира само без да линква т.е.:

Примерен код
g++ -o a.o -c a.cpp


Но виждам, че dvasilev вече ти е дали алтернативен отговор. Препоръчвам ти да се позапознаеш с възможностите на командите, които ползваш преди да почнеш да ги ползваш - man gcc

Цитат (plamen_t @ Дек. 12 2006,18:59)

Btw как да си направя Makefile.


Ами лесно. Ето ти един бърз пример за Makefile:

Примерен код

CXX=g++
CXXFLAGS=-Wall -O2

all: main

main: main.cpp a.o
   $(CXX) $(CXXFLAGS) -o $@ a.o main.cpp

a.o: a.h a.cpp
   $(CXX) $(CXXFLAGS) -o a.o -c a.cpp

clean:
   rm -f a.o
   rm -f main


Забележка: Преди $(CXX) трябва да има табулация! Задължително!

Записваш го като Makefile във каталога със изходния код и след това пишеш
Примерен код
make

или
Примерен код
gmake


Програмата ти ще се бъде изградена от една единствена команда. Повече информация относно GNU make можеш да намериш на офциалната страница.



Активен

Г. Д. Сотиров

astronom

  • Напреднали
  • *****
  • Публикации: 254
    • Профил
Компилиране на програма?
« Отговор #8 -: Dec 13, 2006, 10:18 »
Цитат (TheNightmare @ Дек. 12 2006,21:36)
За най-лесно си сложи някоя среда от рода на Anjuta, Code::Blocks или KDevelop

Една такава среда повече ще го обърка като начинаещ отколкото да му помогне. А и не си заслужава за 30 реда код автоматизирано да генерираш Makefiles и configure - по добре да схванеш нещо.
Активен

Г. Д. Сотиров

plamen_t

  • Напреднали
  • *****
  • Публикации: 170
    • Профил
Компилиране на програма?
« Отговор #9 -: Dec 19, 2006, 16:55 »
Значи разбрах главната идея на make. Само че имам един проблем.
Хедърите на класовете се намират в /usr/local/project/includes, а самата имплементация на тези класове е в /usr/local/project/src. Броят на класовете е сравнително голям и освен това е изградена сложна йерархия на наследяване и затова ми е доста трудно да видя кои точно имплементации ми трябват и да компилирам само тях. Като тръгна да компилирам някоя програма, която използва класовете от /usr/local/project, добавям в makefile-a IPATHS=/usr/local/project/includes. Компилацията е успешна, но когато се пусне линкера и дава постоянно undefined reference към всяка функция, която е от тези класове. Та как мога да го накарам да види на кой хедър, коя имплементация съответства. Нещо подобно на qmake при Qt. qmake автоматично сканира указаните директории и намира на всеки хедър имплементацията и по този начин много лесно се разбива един клас на 2 файла - декларация и дефиниция.
Активен