Forum: PC-Programmierung "unresolved externals" bei statischer Methode


von Maxim (Gast)


Lesenswert?

DE_handler.h
1
#pragma once
2
#include "stdafx.h"
3
4
class DE_handler
5
{
6
public:
7
  int main(void);
8
  DE_handler(void);
9
  static vector<float> mul_vec(vector<float>, float k);
10
  static vector<float> add_vec(vector<float>, vector<float>);
11
};

DE_handler.cpp
1
#include "DE_handler.h"
2
#include "equation.h"
3
4
int main(void)
5
{
6
  float time = 0.0;
7
  float t_end = 10.0;
8
  float h = 1;
9
  vector<float> c; //constants
10
  vector<float> initial; //initial values
11
  vector<float> temp_res; //temporary stored results
12
  vector<vector<float>> results; //calculated results
13
14
  //define vector of constants belonging to the differential equation
15
  c.push_back(1/4);
16
  c.push_back(-1/100);
17
  c.push_back(-1);
18
  c.push_back(1/100);
19
20
  //define initial values
21
  initial.push_back(80.0);
22
  initial.push_back(30.0);
23
24
  equation eq(c);
25
  temp_res = initial;
26
27
  temp_res = DE_handler::add_vec(initial, initial);
28
  cout << temp_res.at(0) << " " << temp_res.at(1);
29
30
  system("Pause");
31
  return 0;
32
}
33
34
static vector<float> mul_vec(vector<float> vec, float k)
35
  {
36
    for(int i = 0; i <= vec.size(); i++)
37
    {
38
      vec.at(i) = vec.at(i)*k;
39
    }
40
    return vec;
41
  }
42
43
static vector<float> add_vec(vector<float> vec1, vector<float> vec2)
44
  {
45
    vector<float> sum;
46
    for(int i = 0; i < vec1.size(); i++)
47
    {
48
      sum.push_back(vec1.at(i)+vec2.at(i));
49
    }
50
    return sum;
51
  }
52
53
DE_handler::DE_handler(void)
54
{
55
}

Die genaue Meldung des Compilers:
"Error  3  error LNK2019: unresolved external symbol "public: static 
class std::vector<float,class std::allocator<float> > __cdecl 
DE_handler::add_vec(class std::vector<float,class std::allocator<float> 
>,class std::vector<float,class std::allocator<float> >)" 
(?add_vec@DE_handler@@SA?AV?$vector@MV?$allocator@M@std@@@std@@V23@0@Z) 
referenced in function _main 
D:\Dokumente\Studium\NDGL\NDGL_P1\NDGL_P1\DE_handler.obj  NDGL_P1
"

Ich komme nicht drauf, was dem Compiler fehlt. Wenn ich die Zeile
1
temp_res = DE_handler::add_vec(initial, initial);
auskommentiere, gibt es diesen Fehler nicht. Anscheinend kann der 
Compiler die Methode add_vec() nicht finden, oder wie?

von g457 (Gast)


Lesenswert?

(u.A.) da..

> static vector<float> add_vec(vector<float> vec1, vector<float> vec2)

..fehlt der Klassenname!

HTH

von Karl H. (kbuchegg)


Lesenswert?

Maxim schrieb:

>
1
> #pragma once
2
> #include "stdafx.h"
3
> 
4
> class DE_handler
5
> {
6
> public:
7
>   int main(void);
8
>   DE_handler(void);
9
>   static vector<float> mul_vec(vector<float>, float k);
10
>   static vector<float> add_vec(vector<float>, vector<float>);
11
> };
12
>

Du sollst nicht Java programmieren, wenn du einen C++ Compiler benutzt.

von Mark B. (markbrandis)


Lesenswert?

Autsch... was hat denn main() in der Deklaration einer Klasse zu suchen? 
:-(

von ... (Gast)


Lesenswert?

Das war aber nicht der Fehler.
Der Linker vermisst eine Funktion DE_handler::add_vec, Du hast aber nur 
add_vec.
Steht hier aber schon mal: 
Beitrag "Re: "unresolved externals" bei statischer Methode"

von Klaus W. (mfgkw)


Lesenswert?

Mark Brandis schrieb:
> Autsch... was hat denn main() in der Deklaration einer Klasse zu suchen?
> :-(

Auch wenn es eher -äh- etwas ungewöhnlich ist, spricht theoretisch
nichts gegen eine Methode main in einer Klasse.

von Mark B. (markbrandis)


Lesenswert?

Klaus Wachtler schrieb:
> Auch wenn es eher -äh- etwas ungewöhnlich ist, spricht theoretisch
> nichts gegen eine Methode main in einer Klasse.

Eh. Wird die dann als Einsprungpunkt genommen? Und wenn es eine 
nicht-statische Methode ist und zur Laufzeit noch kein Objekt dieser 
Klasse instanziiert wurde?

von ... (Gast)


Lesenswert?

Nein, die wird natürlich nicht als Einsprungpunkt genommen. Ist eine 
stinknormale Methode wie jede andere auch.

von Klaus W. (mfgkw)


Lesenswert?

Genau.
Ebenso wie rhein(), donau() und mosel().

von Karl H. (kbuchegg)


Lesenswert?

... schrieb:
> Nein, die wird natürlich nicht als Einsprungpunkt genommen. Ist eine
> stinknormale Methode wie jede andere auch.


Der ganze gepostete Code erzählt allerdings die Geschichte, dass der TO 
das ganze anders sieht :-)

von Klaus W. (mfgkw)


Lesenswert?

Das ist dann sein Problem :-))

von Maxim (Gast)


Lesenswert?

Zu main(): Das Programm wird ausgeführt, auch wenn kein Objekt von 
DE_handler erstellt wurde. Die main()-Methode funktioniert bestens ... 
Wo ist das Problem?

Ansonsten läuft es jetzt. Musste die Klasse vor die Methode schreiben. 
Mit static hatte der Compiler dann auch Probleme. Anscheinend darf 
static vor der Methode nur in der Headerdatei stehen, nicht aber im 
Quellcode, oder?

Ich stolper über viele Sachen in C++, weil ich davor lange in Java 
programmiert habe. Vor allem die ganzen Deklarationen und die 
Headerdateien verwirren mich.

von Klaus (Gast)


Lesenswert?

Maxim schrieb:
> Zu main(): Das Programm wird ausgeführt, auch wenn kein Objekt von
> DE_handler erstellt wurde. Die main()-Methode funktioniert bestens ...
> Wo ist das Problem?

Das funktioniert aber nur, weil du vor main eben nicht den Klassen-Namen 
geschrieben hast. Damit ist deine Funktion main aus der DE_Handler 
Klasse noch undefiniert. Zum Glück rufst du die auch nicht auf, so dass 
der Linker keinen Grund hat zu meckern.

Also: raus mit dem main() aus der Klassendefinition, das hat da nichts 
zu suchen!

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Die Implementierung heißt main und nicht /DE_handler::main/.

Deswegen funktioniert es, der Compiler erwartet ein main auf globaler 
Ebene.

Hättest Du Deine Implementierung /DE_handler::main/ genannt, würde Dich 
der Linker anmotzen, weil er kein main finden kann.

Würde irgendwo /DE_handler::main/ referenziert, würde der Compiler 
motzen, solange es keine Implementierung davon gibt.

> Ich stolper über viele Sachen in C++, weil ich davor lange in Java
> programmiert habe. Vor allem die ganzen Deklarationen und die
> Headerdateien verwirren mich.

Das ist der Vorteil von Java, daß es mit C++ nur die Syntax, sonst 
aber nicht viel gemein hat.

von Karl H. (kbuchegg)


Lesenswert?

Maxim schrieb:

> Ich stolper über viele Sachen in C++, weil ich davor lange in Java
> programmiert habe.

Du stolperst über viele Sachen in C++, weil du versuchst nach der 
Methode 'Versuch und Irrtum' bzw. 'Für einen alten Java Hasen kann das 
doch nicht so schwer sein' an die Sache ran zu gehen.

Hol dir einen Stroustroup aus der nächsten Buchhandlung und arbeite ihn 
von vorne weg durch. Die ersten Kapitel, wo es um Zahlen, Darstellungen 
und dergleichen geht, kannst du oberflächlich überfliegen. Sobald aber 
die ersten Programme im Text auftauchen, solltest du etwas genauer 
lesen. Du wirst vieles entdecken, was ganz ähnlich wie in Java 
funktioniert. Du wirst aber auch noch viel mehr entdecken, was in C++ 
völlig anders gemacht wird.

Zb. Muss in Java jede Funktion ein Member einer Klasse sein.
In C++ aber nicht. Es ist kein Problem freistehende Funktionen zu haben, 
die zu keiner Klasse gehören.

Ganz im Gegenteil: 1 Funktion ist in jedem Programm, welche zu keiner 
Klasse gehört: main()

Und deine static Funktionen:
Diese Funktionen haben ja im eigentlichen Sinn überhaupt nichts mit 
einem DE_Handler zu tun (was immer das auch sein mag). An dieser Stelle 
macht diese Klasse überhaupt keien Sinn! Es sieht so aus, dass du die 
Klasse nur deswegen gebaut hast, weil du von Java gewohnt bist, dass 
jede Funktion in irgendeiner Klasse sein muss.
Aber wie schon gesagt: In C++ ist das nicht so. Man gruppiert Funktionen 
in Klassen, weil es sinnvoll ist, weil diese Funktionen einen 
gemeinsamen Bezug zueinander und zur Klasse haben und nicht weil das 
Sprachkonzept es nicht erlaubt Funktionen ausserhalb von Klassen zu 
haben.

Und wenn du dann im Stroustroup soweit vorgedrungen bist, sollte man 
sich auch einmal über Argument Passing Mechanismen unterhalten :-)

von Rolf Magnus (Gast)


Lesenswert?

Maxim schrieb:

> Mit static hatte der Compiler dann auch Probleme. Anscheinend darf
> static vor der Methode nur in der Headerdatei stehen, nicht aber im
> Quellcode, oder?

Richtig. Das ist etwas seltsam, aber ist nun mal so in C++.

Du solltest dir auch mal die Standardlib anschauen. Für das, was du da 
mit vector<float> machst, wäre std::valarray<float> eine sinnvolle 
Alternative. Da ist das, was deine Funktionen machen, schon als 
Operatoren vordefiniert.
Damit könnten die Funktionen so aussehen:
1
valarray<float> mul_vec(valarray<float> arr, float k)
2
{
3
  arr *= k;
4
  return arr;
5
}
6
7
valarray<float> add_vec(const valarray<float>& arr1, const valarray<float>& arr2)
8
{
9
  return arr1 + arr2;
10
}

Eigentlich braucht man sie also gar nicht mehr.

Übrigens:
1
   vector<vector<float>> results; //calculated results
geht nicht durch einen konformen Compiler. Es müßte heißen:
1
   vector<vector<float> > results; //calculated results

Und warum benutzt du eigentlich überall float statt double? Wenn deine 
Arrays nicht gerade so riesig werden, daß du auf den Speicher achten 
mußt, solltest du grundsätzlich double bevorzugen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.