mikrocontroller.net

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


Autor: Maxim (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
DE_handler.h
#pragma once
#include "stdafx.h"

class DE_handler
{
public:
  int main(void);
  DE_handler(void);
  static vector<float> mul_vec(vector<float>, float k);
  static vector<float> add_vec(vector<float>, vector<float>);
};

DE_handler.cpp
#include "DE_handler.h"
#include "equation.h"

int main(void)
{
  float time = 0.0;
  float t_end = 10.0;
  float h = 1;
  vector<float> c; //constants
  vector<float> initial; //initial values
  vector<float> temp_res; //temporary stored results
  vector<vector<float>> results; //calculated results

  //define vector of constants belonging to the differential equation
  c.push_back(1/4);
  c.push_back(-1/100);
  c.push_back(-1);
  c.push_back(1/100);

  //define initial values
  initial.push_back(80.0);
  initial.push_back(30.0);

  equation eq(c);
  temp_res = initial;

  temp_res = DE_handler::add_vec(initial, initial);
  cout << temp_res.at(0) << " " << temp_res.at(1);

  system("Pause");
  return 0;
}

static vector<float> mul_vec(vector<float> vec, float k)
  {
    for(int i = 0; i <= vec.size(); i++)
    {
      vec.at(i) = vec.at(i)*k;
    }
    return vec;
  }

static vector<float> add_vec(vector<float> vec1, vector<float> vec2)
  {
    vector<float> sum;
    for(int i = 0; i < vec1.size(); i++)
    {
      sum.push_back(vec1.at(i)+vec2.at(i));
    }
    return sum;
  }

DE_handler::DE_handler(void)
{
}

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
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?

Autor: g457 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
(u.A.) da..

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

..fehlt der Klassenname!

HTH

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Maxim schrieb:

>
> #pragma once
> #include "stdafx.h"
> 
> class DE_handler
> {
> public:
>   int main(void);
>   DE_handler(void);
>   static vector<float> mul_vec(vector<float>, float k);
>   static vector<float> add_vec(vector<float>, vector<float>);
> };
> 

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

Autor: Mark Brandis (markbrandis)
Datum:

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

Autor: ... (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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"

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Mark Brandis (markbrandis)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: ... (Gast)
Datum:

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

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Genau.
Ebenso wie rhein(), donau() und mosel().

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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 :-)

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist dann sein Problem :-))

Autor: Maxim (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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 :-)

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
valarray<float> mul_vec(valarray<float> arr, float k)
{
  arr *= k;
  return arr;
}

valarray<float> add_vec(const valarray<float>& arr1, const valarray<float>& arr2)
{
  return arr1 + arr2;
}


Eigentlich braucht man sie also gar nicht mehr.

Übrigens:
   vector<vector<float>> results; //calculated results
geht nicht durch einen konformen Compiler. Es müßte heißen:
   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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.