Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / Ошибка линковки при объявлении функции А в определении функции Б. / 13 сообщений из 13, страница 1 из 1
18.06.2013, 17:57
    #38302076
Compositum
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка линковки при объявлении функции А в определении функции Б.
Доброго времени суток.

Приведённый ниже код успешно компилируется:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
	Point get_offset_point(Point,double,double);
//---------------------------------------------------------------------------
	Arrow::Arrow(Point p0, double angle, double length, Arrow_style style): 
		ang(angle), len(length), s(style){
			Point p1 = get_offset_point(p0,angle,length);
			Point p2 = get_offset_point(p0,angle+10,length/2);
			Point p3 = get_offset_point(p0,angle-10,length/2);

			// стрелка указывает:			
			add(p0); // куда
			add(p1); // откуда
			// засечки
			add(p2);
			add(p3);
	}


Однако, я хочу объявление функции get_offset_point переместить в определение Arrow::Arrow, т.к. она используется только в этом конструкторе. Пишу так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
//---------------------------------------------------------------------------
	Arrow::Arrow(Point p0, double angle, double length, Arrow_style style): 
		ang(angle), len(length), s(style){

			Point get_offset_point(Point,double,double);

			Point p1 = get_offset_point(p0,angle,length);
			Point p2 = get_offset_point(p0,angle+10,length/2);
			Point p3 = get_offset_point(p0,angle-10,length/2);

			// стрелка указывает:			
			add(p0); // куда
			add(p1); // откуда
			// засечки
			add(p2);
			add(p3);
	}


Однако в результате получаю ошибку линковки:
Errors
Error 85 error LNK1120: 1 unresolved externals C:\bs\13\ch13\Debug\ch13.exe 1 1 ch13
Error 84 error LNK2019: unresolved external symbol "struct Point __cdecl get_offset_point(struct Point,double,double)" (?get_offset_point@@YA?AUPoint@@U1@NN@Z) referenced in function "public: __thiscall Bushman::Arrow::Arrow(struct Point,double,double,struct Bushman::Arrow_style)" (??0Arrow@Bushman@@QAE@UPoint@@NNUArrow_style@1@@Z) C:\bs\13\ch13\arrow.obj ch13


Почему линковщик не находит функцию во втором варианте?

Спасибо.
...
Рейтинг: 0 / 0
18.06.2013, 18:28
    #38302133
White Owl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка линковки при объявлении функции А в определении функции Б.
CompositumОднако, я хочу объявление функции get_offset_point переместить в определение Arrow::Arrow, т.к. она используется только в этом конструкторе.В С++ не бывает вложенных функций.
Если хочешь ограничить видимость, вынеси конструктор в отдельный .cpp, положи рядом эту функцию и объяви ее static.

А вообще, зачем тебе глобальная функция с ограниченной видимостью? То что ты хочешь обычно делают через приватные функции или приватные классы.
...
Рейтинг: 0 / 0
18.06.2013, 18:35
    #38302140
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка линковки при объявлении функции А в определении функции Б.
White OwlВ С++ не бывает вложенных функций.

Это не вложеная функция, а вложенный прототип функции - второе разрешено.
...
Рейтинг: 0 / 0
18.06.2013, 18:37
    #38302149
Compositum
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка линковки при объявлении функции А в определении функции Б.
Попробовал прописать полное имя, получил ещё более странные ошибки.
Код
Код: plaintext
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.
77.
78.
79.
/*
arrow.cpp
© Andrey Bushman, 18 Jun 2013
Chapter 13, exercise 3.
*/
//---------------------------------------------------------------------------
#include "arrow.h"
//*****************************************************************************
namespace Bushman{
	// Point get_offset_point(Point,double,double);
//---------------------------------------------------------------------------
	Arrow::Arrow(Point p0, double angle, double length, Arrow_style style): 
		ang(angle), len(length), s(style){

			Point Bushman::get_offset_point(Point,double,double);

			Point p1 = Bushman::get_offset_point(p0,angle,length);
			Point p2 = Bushman::get_offset_point(p0,angle+10,length/2);
			Point p3 = Bushman::get_offset_point(p0,angle-10,length/2);

			// стрелка указывает:			
			add(p0); // куда
			add(p1); // откуда
			// засечки
			add(p2);
			add(p3);
	}
//---------------------------------------------------------------------------
	Point get_offset_point(Point p0, double angle, double length){

		if(length < 0) 
			throw runtime_error("Invalid length value: " + to_string(length));

		if(angle > 360 || angle < -360) 
			throw runtime_error("Invalid angle value: " + to_string(angle));

		if(angle < 0) angle = 360 - abs(angle);

		// если угол не прямой, то переводим его в радианы.
		if(angle != 0 && angle != 90 && angle != 180 && angle != 270) 
			angle *= 3.14159265/180;

		// Определяю начало стрелки	(точка p1)	
		Point p1;
		if(angle == 0 || angle == 360){
			p1.x = p0.x + length;
			p1.y = p0.y;
		}
		else if(angle < 90){
			p1.x = p0.x + length * cos(angle);
			p1.y = p0.y - length * sin(angle);
		}
		else if(angle == 90){
			p1.y = p0.y - length;
			p1.x = p0.x;
		}
		else if(angle < 180){
			p1.x = p0.x - length * cos(180 - angle);
			p1.y = p0.y - length * sin(180 - angle);
		}
		else if(angle == 180){
			p1.x = p0.x - length;
			p1.y = p0.y;
		}
		else if(angle < 270){
			p1.x = p0.x - length * cos(270 - angle);
			p1.y = p0.y + length * sin(270 - angle);
		}
		else if(angle == 270){
			p1.x = p0.x;
			p1.y = p0.y + length;
		}		
		else if(angle < 360){
			p1.x = p0.x + length * cos(360 - angle);
			p1.y = p0.y + length * sin(360 - angle);
		}
		return p1;
	}
}



Errors
Error 33 error C2039: 'get_offset_point' : is not a member of 'Bushman' c:\bs\13\ch13\arrow.cpp 15 1 ch13
Error 34 error C2039: 'get_offset_point' : is not a member of 'Bushman' c:\bs\13\ch13\arrow.cpp 17 1 ch13
Error 35 error C2039: 'get_offset_point' : is not a member of 'Bushman' c:\bs\13\ch13\arrow.cpp 18 1 ch13
Error 36 error C2039: 'get_offset_point' : is not a member of 'Bushman' c:\bs\13\ch13\arrow.cpp 19 1 ch13

Странно, ведь функция находится именно в том пространстве имён, которое я указал... Вроде делаю по правилам: объявил, прежде чем использовал, причём сделал это даже в стиле C (разместил объявление в самом начале кода).
авторВ С++ не бывает вложенных функций.

Я в курсе. Кроме того, в моём коде их и нет.
авторЕсли хочешь ограничить видимость, вынеси конструктор в отдельный .cpp, положи рядом эту функцию и объяви ее static.

Я знаю об этом способе. Однако меня всё же интересует, почему на заработал способ, указанный мною.
White OwlА вообще, зачем тебе глобальная функция с ограниченной видимостью? То что ты хочешь обычно делают через приватные функции или приватные классы.

Функцию стоит делать приватной лишь в том случае, если для её работы необходим доступ к закрытым членам класса. В моём случае такой необходимости нет.
...
Рейтинг: 0 / 0
18.06.2013, 18:39
    #38302151
Compositum
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка линковки при объявлении функции А в определении функции Б.
CompositumФункцию стоит делать приватной лишь в том случае, если для её работы необходим доступ к закрытым членам класса. В моём случае такой необходимости нет.
очепятка. Правильно так:
CompositumФункцию стоит включать в состав интерфейса лишь в том случае, если для её работы необходим доступ к закрытым членам класса. В моём случае такой необходимости нет.
...
Рейтинг: 0 / 0
18.06.2013, 18:45
    #38302165
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка линковки при объявлении функции А в определении функции Б.
CompositumСтранно, ведь функция находится именно в том пространстве имён, которое я
указал...
Нет. В лучшем случае она в Bushman::Arrow.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
18.06.2013, 18:49
    #38302174
Compositum
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка линковки при объявлении функции А в определении функции Б.
Dimitry SibiryakovНет. В лучшем случае она в Bushman::Arrow.
С какого перепугу? В интерфейс я её не включал:
интерфейс
Код: plaintext
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.
/*
arrow.h
© Andrey Bushman, 18 Jun 2013
Chapter 13, exercise 3.
*/
//---------------------------------------------------------------------------
#ifndef BUSH_ARROW_H
#define BUSH_ARROW_H
#include "../Point.h"
#include "../Graph.h"
//*****************************************************************************
namespace Bushman{
//---------------------------------------------------------------------------
	struct Arrow_style{
		enum Arrow_style_type{ none, lines, filled, unfilled};
		Arrow_style(Arrow_style_type style): s(style) {}
		Arrow_style_type style() const { return s; }
	private:
		Arrow_style_type s;
	};
//---------------------------------------------------------------------------
	class Arrow: public Graph_lib::Shape 
	// Arrow
	{
	public:
		Arrow(Point p0, double angle, double length, Arrow_style style);
		void draw_lines() const;
		double angle() const { return ang; }
		double length() const { return len; }
		void set_angle(double val) { ang = val; }
		void set_length(double val) { len = val; }
		Arrow_style style() const { return s; }
		void set_style(Arrow_style val) { s = val; }
	private:		
		double ang,len;
		Arrow_style s; 
	};
}
#endif


...
Рейтинг: 0 / 0
18.06.2013, 18:52
    #38302178
Ошибка линковки при объявлении функции А в определении функции Б.
В принципе так можно.
http://ideone.com/UaWCBh

Compositum , у вас функция get_offset_point():
1. не является членом класса
2. не объявлена как static
3. не объявлена как inline
?
...
Рейтинг: 0 / 0
18.06.2013, 18:53
    #38302181
Compositum
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка линковки при объявлении функции А в определении функции Б.
не: static, inline, член классаВ принципе так можно.
http://ideone.com/UaWCBh

Compositum , у вас функция get_offset_point():
1. не является членом класса
2. не объявлена как static
3. не объявлена как inline
?
"да" по всем трём.
...
Рейтинг: 0 / 0
18.06.2013, 19:15
    #38302216
Compositum
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка линковки при объявлении функции А в определении функции Б.
не: static, inline, член классаВ принципе так можно.
http://ideone.com/UaWCBh
Я показывал несколько иной вариант. То, что в функциях можно размещать объявления др. функций, я в курсе, т.к. сам это неоднократно делал ранее.

Упрощённо, вот вариант, демонстрирующий обозначенную мною проблему кратко и наглядно:
Код: plaintext
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.
/*
test.cpp
© Andrey Bushman, 18 Jun 2013
*/
//--------------------------------------------
#include <exception>
#include <iostream>
using namespace std;
//--------------------------------------------
namespace Bushman{
//--------------------------------------------
	class MyClass{
	public:
		MyClass();
	};
//--------------------------------------------
	MyClass::MyClass(){
		void func(); // объявил
		func(); // вызвал
	}
//--------------------------------------------
	void func(){
		cout << "Ping..." << endl;
	}
}
//============================================
int main()
try{
	namespace B = Bushman;
	B::MyClass a;
}
catch(exception& e){
	cerr << e.what() << endl;
	return 1;
}
catch(...){
	cerr << "Unknown exception." << endl;
	return 2;
}


Во время компиляции (MS VS 2012) получаю такой результат:
LinkC:\bs\13>cl test.cpp /EHsc
Microsoft (R) C/C++ Optimizing Compiler Version 17.00.51106.1 for x64
Copyright (C) Microsoft Corporation. All rights reserved.

test.cpp
Microsoft (R) Incremental Linker Version 11.00.51106.1
Copyright (C) Microsoft Corporation. All rights reserved.

/out:test.exe
test.obj
test.obj : error LNK2019: unresolved external symbol "void __cdecl func(void)" (
?func@@YAXXZ) referenced in function "public: __cdecl Bushman::MyClass::MyClass(
void)" (??0MyClass@Bushman@@QEAA@XZ)
test.exe : fatal error LNK1120: 1 unresolved externals

C:\bs\13>
...
Рейтинг: 0 / 0
18.06.2013, 19:45
    #38302242
Ошибка линковки при объявлении функции А в определении функции Б.
Сейчас проверил, в GCC 4.3.2/4.7.2 компилируется, в MSVS 2010/2012 ругается.
Хз в чем затык, то ли по стандарту надо как-то по другому делать, то ли MSVS стандарт не держит.
...
Рейтинг: 0 / 0
18.06.2013, 19:59
    #38302253
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка линковки при объявлении функции А в определении функции Б.
По стандарту, если прототип объявлен внутри функции находящейся в неймспейсе, то у прототипа будет тот же неймспейс.
А в вашем случае VS считает его глобальным.
Т.е. это баг в VS.
...
Рейтинг: 0 / 0
18.06.2013, 20:04
    #38302255
Compositum
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка линковки при объявлении функции А в определении функции Б.
Anatoly Moskovsky,

Здесь как-то тоже больше склоняются к тому, что это специфично для MS VS.
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / Ошибка линковки при объявлении функции А в определении функции Б. / 13 сообщений из 13, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]