2013 09 17_c++_lecture_02

22
Лекция 2. Сборка С++ программ С++ Basics. Valery Lesin, 2013 1

Upload: cs-center

Post on 13-Dec-2014

3.091 views

Category:

Documents


1 download

DESCRIPTION

 

TRANSCRIPT

Page 1: 2013 09 17_c++_lecture_02

Лекция 2. Сборка С++

программ

С++ Basics. Valery Lesin, 2013 1

Page 2: 2013 09 17_c++_lecture_02

Компиляция

С++ Basics. Valery Lesin, 2013 2

Page 3: 2013 09 17_c++_lecture_02

Объявления и определения

• Объявлений может быть много

• Определение должно быть ровно одно

С++ Basics. Valery Lesin, 2013 3

1.

2.

3.

4.

5.

6.

7.

8.

9.

10.

11.

12.

13.

// declarations

void foo(int bar);

extern int value;

// definitions

void foo(int bar)

{

return bar + 5;

}

int value;

double e = 2.71;

Page 4: 2013 09 17_c++_lecture_02

Объявление функции

1.

2.

3.

4.

5.

6.

7.

//-- file1.cpp

#include <iostream>

void greet()

{

std::cout << "Hello, World!" << std::endl;

}

С++ Basics. Valery Lesin, 2013 4

1.

2.

3.

4.

5.

6.

7.

8.

//-- file2.cpp

void greet();

int main()

{

greet();

return 0;

}

Page 5: 2013 09 17_c++_lecture_02

Примеры объявлений/определений

1.

2.

3.

4.

//-- file1.cpp

int uno = 1;

int due = 2;

extern int tre;

С++ Basics. Valery Lesin, 2013 5

1.

2.

3.

4.

5.

6.

7.

8.

9.

10.

11.

//-- file2.cpp

int uno;

extern double due;

extern int tre;

int main()

{

due = 2.71;

tre = 3;

return 0;

}

1.

2.

3.

1>file2.obj : error LNK2005: "int uno" (?uno@@3HA) already defined in file1.obj

1>file2.obj : error LNK2001: unresolved external symbol "int tre" (?tre@@3HA)

1>file2.obj : error LNK2001: unresolved external symbol "double due" (?due@@3NA)

Page 6: 2013 09 17_c++_lecture_02

Внешняя компоновка (external linkage)

• Имя используется в другой единице

трансляции нежели ее определение

С++ Basics. Valery Lesin, 2013 6

1.

2.

3.

//-- file1.cpp

extern int uno;

int foo(int bar);

1.

2.

3.

4.

5.

6.

//-- file2.cpp

int uno = 5;

int foo(int bar)

{

return bar + 5;

}

Page 7: 2013 09 17_c++_lecture_02

Внутренняя компоновка (internal linkage)

С++ Basics. Valery Lesin, 2013 7

1.

2.

3.

4.

5.

6.

7.

8.

9.

10.

11.

//-- file1.cpp

static int uno = 5; // be careful with ‘static’ – too many meanings

const double due = 2.71;

namespace

{

int answer()

{

return 42;

}

}

1.

2.

3.

4.

5.

6.

7.

8.

9.

10.

11.

12.

13.

//-- file2.cpp

extern double due;

int answer()

{

return 43;

}

int main()

{

due = 5; // error LNK2001: unresolved external symbol "double due" (?due@@3NA)

return 0;

}

Page 8: 2013 09 17_c++_lecture_02

Заголовочные файлы (headers)

С++ Basics. Valery Lesin, 2013 8

1.

2.

//-- header1.h

int factorial(int n);

1.

2.

3.

4.

5.

6.

7.

8.

9.

10.

//-- source1.cpp

#include "header1.h"

int factorial(int n)

{

int res = 1;

while (n > 1)

res *= n--;

return res;

}

1.

2.

3.

4.

5.

6.

7.

8.

9.

//-- source2.cpp

#include <iostream>

#include "header1.h"

int main()

{

std::cout << factorial(6) << std::endl;

return 0;

}

Page 9: 2013 09 17_c++_lecture_02

Что включать в header?

• Включать все то, что планируется использовать в нескольких единицах трансляции:

– определение типов struct vector{inx; int y};

– определение/объявление шаблонов

– объявление функций

– определение встроенных(inline) функций

– объявления (только!) переменных

– определения констант, …

С++ Basics. Valery Lesin, 2013 9

Page 10: 2013 09 17_c++_lecture_02

А что нет?

• Может привести к ошибкам:

– определение функций

– определение данных

– анонимные пространства имен

• Типичная ошибка:

– error LNK2005: "int a" (?a@@3HA)

already defined in source1.obj

С++ Basics. Valery Lesin, 2013 10

Page 11: 2013 09 17_c++_lecture_02

Встроенные функции

С++ Basics. Valery Lesin, 2013 11

1.

2.

3.

4.

5.

6.

7.

8.

9.

//-- header1.h

inline int factorial(int n)

{

int res = 1;

while (n > 1)

res *= n--;

return res;

}

• Выбирается одна из всех единиц трансляции (поэтому должны быть одинаковы)

• Может встраиваться в код для оптимизации (по усмотрению компилятора)

Page 12: 2013 09 17_c++_lecture_02

One Definition Rule• Два определения одной и той же встроенной

функции (класса или шаблона) в разных единицах трансляции:

– должны совпадать лексема за лексемой

– смыл лексем должен быть одинаков

• Пишите самодостаточные заголовочные файлы

С++ Basics. Valery Lesin, 2013 12

1.

2.

3.

//-- source1.cpp

struct vector {int x; int y;};

#include "header1.h"

1.

2.

3.

//-- source2.cpp

struct vector {double x; double y;};

#include "header1.h"

1.

2.

//-- header1.h

inline double length(vector v) {/*...*/ }

Page 13: 2013 09 17_c++_lecture_02

“Глобальные переменные” в хидере*

С++ Basics. Valery Lesin, 2013 13

1.

2.

3.

4.

5.

6.

//-- header1.h

inline double& global_time()

{

static double time = init_time();

return time;

}

• Популярный трюк, если у Вас нет cpp-файла

для определения переменной

Page 14: 2013 09 17_c++_lecture_02

Компоновка с кодом не на С++

• Совместимо с C, assembler, Delphi

• Не меняет правил компиляции, только линковки

• Name mangling:

С++ Basics. Valery Lesin, 2013 14

1.

2.

3.

4.

5.

6.

7.

extern "C" int foobar(double value);

extern "C"

{

void foo();

void bar();

extern double x;

};

1.

2.

C language: _foobar

C++ language: ?foobar@@YAHN@Z

Page 15: 2013 09 17_c++_lecture_02

Пара слов про условную компиляцию

С++ Basics. Valery Lesin, 2013 15

1.

2.

3.

4.

5.

6.

7.

8.

9.

#define PI 3.14

#ifdef PI

...

#endif

#if defined(PI)

...

#endif

1.

2.

3.

4.

5.

6.

7.

#if

...

#elif

...

#else

...

#endif

Page 16: 2013 09 17_c++_lecture_02

Стражи включения• Лучше делать самодостаточные хидеры

– не переусердствуйте – увеличиться время компиляции

– библиотечные хидера включайте в precompiled header*

• Избегайте повторного включения:

С++ Basics. Valery Lesin, 2013 16

1.

2.

3.

4.

5.

6.

7.

8.

9.

10.

11.

//-- header1.h

#ifndef __HEADER_1__

#define __HEADER_1__

...

#endif

//-- header2.h

#pragma once

...

Page 17: 2013 09 17_c++_lecture_02

Инициализация глобальных

переменных

• Если не указана инициализирующая часть, присваивается значение типа по умолчанию (ноль)

• Инициализируются в порядке описания в единице трансляции

• Между разными единицами трансляции порядок инициализации не определен

• Рекомендация: старайтесь не использовать глобальные переменные. Если очень надо –лучше трюк с inline функцией.

С++ Basics. Valery Lesin, 2013 17

Page 18: 2013 09 17_c++_lecture_02

Сборка из нескольких файлов

С++ Basics. Valery Lesin, 2013 18

1. g++ main.cpp hello.cpp factorial.cpp -o hello

• Можно собрать из командной строки

• А можно сделать Makefile1.

2.

3.

4.

5.

6.

цель: зависимости

[tab] команда

#################################################

all:

g++ main.cpp hello.cpp factorial.cpp factorial.h hello.h -o hello

Page 19: 2013 09 17_c++_lecture_02

Простой Makefile

• Для сборки достаточно запустить команду make

С++ Basics. Valery Lesin, 2013 19

1.

2.

3.

4.

5.

6.

7.

8.

9.

10.

11.

12.

13.

14.

15.

16.

all: hello

hello: main.o factorial.o hello.o

g++ main.o factorial.o hello.o -o hello

main.o: main.cpp

g++ -c main.cpp

factorial.o: factorial.cpp factorial.h

g++ -c factorial.cpp

hello.o: hello.cpp hello.h

g++ -c hello.cpp

clean:

rm -rf *.o hello

Page 20: 2013 09 17_c++_lecture_02

Еще более простой Makefile

С++ Basics. Valery Lesin, 2013 20

1.

2.

3.

4.

5.

6.

7.

8.

9.

10.

11.

12.

13.

objects = main.o hello.o factorial.o

hello : $(objects)

g++ -o hello $(objects)

main.o : main.cpp

hello.o : hello.h

factorial.o: factorial.h

.PHONY : clean

clean :

-rm edit $(objects)

• Указывая флаги компиляции, обязательно делайте их одинаковыми (за исключением спец. случаев)

Page 21: 2013 09 17_c++_lecture_02

Precompiled headers*

С++ Basics. Valery Lesin, 2013 21

• Позволяют значительно сэкономить время компиляции для библиотечных хидеров

Page 22: 2013 09 17_c++_lecture_02

Вопросы?

С++ Basics. Valery Lesin, 2013 22