Willkommen ~Gast!
Registrieren || Einloggen || Hilfe/FAQ || Staff
Probleme mit der Registrierung im Forum? Melde dich unter registerEin Bild.
Autor Beitrag
000
06.04.2002, 18:46
Kriz



Brrrr,

kann mir mal einer von den Herrn Coderkollegen erklären, wieso meine statische Win32-Lib nur dann funzt, wenn dort simple Funktionen definiert werden und dann wiederum nicht funzt, wenn ich eine Klasse da reinpacke? Beispiel:

Gemeinsame Headerdatei für die Lib und das TestprogrammQuellcode:// testlib.h

int GetInt(void);
class TestClass;

Quelldatei der LibraryQuellcode:// testlib.cpp

#include "testlib.h"

int GetInt()
{
....return 100;
}

class TestClass
{
public:
....TestClass() : val(500) {}
....int val;
};

Quelldatei des TestprogrammsQuellcode:// testprg.cpp
#include <iostream.h>
#include "testlib.h"

int main()
{
....TestClass c;
....cout << GetInt()
.........<< "\n"
.........<< c.val
.........<< endl;
....return 0;
}

Wie gesagt, die Lib wird anständig eingebunden, nur spuckt VC++ dann folgendes aus:

error C2027: Verwendung des undefinierten Typs "TestClass"
plus die Errors für c.val, daß er die net kennt.

Dann habe ich "extern TestClass c;" probiert, obwohl das ja schwachsinnig ist, denn die Header wird ja eingebunden mit der Deklaration. Aber selbst so hat es nicht gefunzt. Funzen tut es nur, wenn ich die Klasse rauskommentiere. Dann geht die Library wunderbar, d.h. GetInt() funzt. Aber wie zum Henker schaffe ich es, daß diese Klasse im Testprogramm erkannt wird? Das geht, denn die MSDN weist ausdrücklich darauf hin (wäre auch komisch, wenn eine C++ Library keine Klassen verarbeiten könnte.

Cu

EDIT - Habe Instanz class in c geändert o_O (Nur damit's keine doofen Bemerkungen gibt =)

--

K:R-I)Z++
"CSS ist cascading style sheets. Und nicht so'n Ranzspiel." - dp
In memory of Voice († 2005/03/30)


Dieser Beitrag wurde am 06.04.2002 um 19:38 von Kriz bearbeitet.
zum Seitenanfang zum Seitenende Profil || Suche
001
06.04.2002, 20:35
mani



w00t w00t
kriz du trottel :P

ganz einfach:

lib.cpp:
Quellcode:
#include "lib.h"

int GetInt()
{
    return 100;
}

void TestClass::Set(int a)
{
    val = a;
}

int TestClass::Get()
{
    return val;
}

lib.h:
Quellcode:
int GetInt(void);
class TestClass
{
public:
    int val;
    void Set(int);
    int Get();
};

main.cpp:
Quellcode:
#include <stdio.h>
#include "lib.h"

int main()
{

    TestClass c;
    c.Set(5);
    printf("%d %d\n", GetInt(), c.Get());
    return 0;
}

ich werd verrückt :O codeeinrücken funzt

--


Dieser Beitrag wurde am 06.04.2002 um 20:41 von mani bearbeitet.
zum Seitenanfang zum Seitenende Profil || Suche
002
06.04.2002, 20:44
Kriz



Das Ergebnis nach 1.5 Std. Query...

Hehehe

Also zusammengefaßt:

eine reine Klassendeklaration in der Header mit anschließender Definition in der Quelldatei is nicht drin! Man muß also tatsächlich die Definition in die header verlegen, ehe das geht!

--

K:R-I)Z++
"CSS ist cascading style sheets. Und nicht so'n Ranzspiel." - dp
In memory of Voice († 2005/03/30)


Dieser Beitrag wurde am 06.04.2002 um 20:45 von Kriz bearbeitet.
zum Seitenanfang zum Seitenende Profil || Suche
003
07.04.2002, 00:48
Another1



is doch logisch, wo soll denn der compiler beim compilieren des hauptprogramms (main.cpp oso) aus sonem header:

int GetInt(void);
class TestClass;

die klassendefinition für die Instanz der selbigen herholen?
Der included doch nich automatisch den Rest ausser testlib.cpp sondern nur die .h, und da steht nunmal nur class TestClass (forward typ deklaration oso) drinne.
[edit]
du hättest natürlich testlib.cpp in deiner main.cpp includen können, aber das wollen wir doch nich, gell?

--

Another1

...relaxing..atm =)
... und Schweiz suckt!


Dieser Beitrag wurde am 07.04.2002 um 00:49 von Another1 bearbeitet.
zum Seitenanfang zum Seitenende Profil || Suche
004
07.04.2002, 02:02
Kriz



Nun ja, meine ursprüngliche Idee basierte auf folgender Überlegung:

Ich schreibe eine statische Library, bestehend aus der Headerdatei für andere Programme und der passenden Quelldatei.

Überlegung #1:

Die Quelldatei wird nach dem Kompilieren in eine Library übersetzt und ist Dritten damit nicht mehr (offensichtlich) zugänglich. Das heißt ja nichts anderes als daß die Prototypen von Funktionen in der Headerdatei liegen und die dazugehörigen Implementierungen in der (späteren) Library.

Überlegung #2:

Wenn ich aber jetzt eine Klasse in der Header bekanntmache (class TestClass;), dann wäre es ja nur von Nutzen, wenn Prototyp und (!) Implementierung in der Library stehen und Dritten dann nicht mehr ersichtlich sind, weil ein Dritter sonst dahergehen kann und private/geschützte Elemente und Methoden ohne Rücksicht öffentlich machen kann und so der Sinn der Klasse hinwegfegt.

Da die Implementierung von Methoden in C++ keine zwingend zusätzlichen Zugriffsattribute kennt (wie das in Java z.B. der Fall ist), kann ein Dritter also leicht aus der MethodeQuellcode:private:
    int Trallalla(void);
ne MethodeQuellcode:public:
    int Trallalla(void);
machen und so den Zugriffsschutz der Klasse aushebeln. Und das ist ja nicht der Sinn der Sache, oder?

Das waren die Gründe, warum ich in der Header nur class TestClass; schreiben wollte...

--

K:R-I)Z++
"CSS ist cascading style sheets. Und nicht so'n Ranzspiel." - dp
In memory of Voice († 2005/03/30)


Dieser Beitrag wurde am 07.04.2002 um 02:04 von Kriz bearbeitet.
zum Seitenanfang zum Seitenende Profil || Suche
005
07.04.2002, 11:10
Tron



klar, dass das mit ner reinen forward-derklartion nicht funzt!
aber diese umgehung, die du beschrieben hast hat ein undefinertes ergebnis!
sie ist NICHT (ANSI-)C++ konform.

zumindest einen kleinen gegentrick kannst du anwenden: (obwohl der genauso unkonform ist)
du deklarierst einfach alle nicht-virtuellen privaten methoden nicht in der headerdatei.
aber dann kann man immer noch alle daten-member 'publicen' ): (hihi... denglisch rulz)

--

'KEINE PANIK' - aus der Triologie in fuenf Baenden von Douglas Adams

'FÜR DEINN FERD' - aus 'Gevatter Tod' von Terry Pratchett

zum Seitenanfang zum Seitenende Profil || Suche
006
07.04.2002, 16:42
Prefect



Naja, private/protected ist schließlich nicht für Sicherheit gegen Hacker, sondern für Sicherheit gegen dumme Programmierer gedacht.

Trotzdem: wenn du möglichst viele Implementationsdetails "verstecken" willst würde ich sowas machen:

Quellcode:
// header
class Foo {
public:
  static Foo *New();

  virtual void bar() = 0;
  virtual void blahblah() = 0;
};

Quellcode:
// cpp

class FooImpl : public Foo {
private:
  int data;
public:
  void bar();
  void blahblah();

};
Foo *Foo::New()
{
  return new FooImpl;
}

Wenn virtuelle Methoden nicht gewünscht sind, könnte man natürlich ein paar Methoden nicht-virtuell in Foo deklarieren, würde mit ein bißchen gehacke genauso gehen. Aber das ist der Aufwand dann wohl doch nicht wert ;)

cu,
Prefect

--

Widelands - Gemütliche Aufbaustrategie, Free Software
Noch ein Blog - Lerne, wie die Welt wirklich ist, aber vergiss niemals, wie sie sein sollte.

zum Seitenanfang zum Seitenende Profil || Suche