Frage zu C++

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
Benutzeravatar
weedy
Beiträge: 585
Registriert: 02.11.2002 21:47:49
Lizenz eigener Beiträge: GNU General Public License
Kontaktdaten:

Frage zu C++

Beitrag von weedy » 18.05.2003 18:59:10

ich habe hier eine Klasse:

class A
{
public:

A()
{

g=&A::f;
}

int f(){ printf( "f\n");}
int (A::*g)( void);

int h(){ (this->*A::g)();} // ok
int i(){ ((*this).*g)();} // ok
};

Die Memberfunktionen h und i können gerufen werden und rufen ihrererseits g auf, welches ein Funktionspointer auf f ist. Ich möchte jetzt aber den Funktionspointer g ausserhalb der Klasse A aufrufen,
so wie ich es in der Klasse A in den Memberfunktionen h und i tue.
Weiss einer, wie das möglich ist?

Danke im Voraus.

weedy.

Benutzeravatar
pdreker
Beiträge: 8298
Registriert: 29.07.2002 21:53:30
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: Nürnberg

Beitrag von pdreker » 18.05.2003 19:07:10

Dazu musst Du den f-Pointer als public deklarieren, was aber gelinde gesagt sch**ße ist, weil dann jeder diesen Pointer manipulieren kann. Read-only realisiert man halt mit einem Akzessor (getF(), f bleibt private, getF() ist public).

Aaaaber: Wenn Du die Functionpointer wirklich brauchst, dann hast Du schon vorher was falsch gemacht. Goto ist schon eine "schlechte" Programmkonstruktion, aber Functionpointer sind böse. Es geht grundsätzlich ohne Functionpointer, und diese alternativen Lösungen sind auch besser lesbar, typsicher und weniger fehleranfällig.

Patrick
Definitely not a bot...
Jabber: pdreker@debianforum.de

Benutzeravatar
weedy
Beiträge: 585
Registriert: 02.11.2002 21:47:49
Lizenz eigener Beiträge: GNU General Public License
Kontaktdaten:

Beitrag von weedy » 18.05.2003 20:49:02

pdreker hat geschrieben:...
Du liegst komplett daneben.

weedy

Benutzeravatar
hagish
Beiträge: 36
Registriert: 13.05.2002 19:13:49
Kontaktdaten:

Beitrag von hagish » 18.05.2003 23:54:58

ich denke auch, daß man functionpinter so gut es geht vermeiden sollte, aber wenn man sie doch mal braucht, hilft vielleicht das: http://www.function-pointer.org/CCPP/FPT/em_fpt.html

Benutzeravatar
weedy
Beiträge: 585
Registriert: 02.11.2002 21:47:49
Lizenz eigener Beiträge: GNU General Public License
Kontaktdaten:

Beitrag von weedy » 19.05.2003 00:21:28

hagish hat geschrieben:ich denke auch, daß man functionpinter so gut es geht vermeiden sollte, aber wenn man sie doch mal braucht, hilft vielleicht das: http://www.function-pointer.org/CCPP/FPT/em_fpt.html
Danke. Das macht einen guten Eindruck.

weedy.

Benutzeravatar
pdreker
Beiträge: 8298
Registriert: 29.07.2002 21:53:30
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: Nürnberg

Beitrag von pdreker » 19.05.2003 02:23:28

OK, ich habe das "public" oben übersehen (benutze [ code ] und [ /code ]), aber ich bleibe dabei: Functionpointer sind ein Zeichen schlechter Planung (es sei denn man bekommt eine Aufgabe, die sagt, dass man f-Pointer benutzen soll).

Achja: der IMO einzig wirklich sinnvolle Grund *f() einzusetzen: http://www.ioccc.org

Und nochwas: Wenn Du BBCode in Deinen Posts benutzt, dann aktivier das auch. Ich habe das für Deinen beiden letzten Posts 'mal gemacht.

Patrick
Definitely not a bot...
Jabber: pdreker@debianforum.de

Benutzeravatar
weedy
Beiträge: 585
Registriert: 02.11.2002 21:47:49
Lizenz eigener Beiträge: GNU General Public License
Kontaktdaten:

Beitrag von weedy » 19.05.2003 06:59:44

Schau dir doch mal den Kernelcode an.
Die Module füllen ganze Strukturen mit Funktionspointern
aus. bsp: ramfs/inode.c:

static struct inode_operations ramfs_dir_inode_operations = {
create: ramfs_create,
lookup: ramfs_lookup,
link: ramfs_link,
unlink: ramfs_unlink,
symlink: ramfs_symlink,
mkdir: ramfs_mkdir,
rmdir: ramfs_rmdir,
mknod: ramfs_mknod,
rename: ramfs_rename,
};

Eine saubere und flexible Lösung meiner Meinung nach.
Nur so ist es überhaupt möglich, Module zur Laufzeit einzubinden.

weedy.

Benutzeravatar
weedy
Beiträge: 585
Registriert: 02.11.2002 21:47:49
Lizenz eigener Beiträge: GNU General Public License
Kontaktdaten:

Ich habe jetzt die Lösung

Beitrag von weedy » 19.05.2003 11:00:52

//und die möchte ich euch jetzt nicht vorehthalten.

//los gehts:

Code: Alles auswählen

extern "C"
{
#include <stdio.h>
}

class A
{
 public:

 A()
 {
  g=&A::f;
 }

 int f() { printf( "f\n");}

 int (A::*g)( void);

 int h(){ (this->*A::g)();} // ok
 int i(){ ((*this).*g)();} // ok

 int k(){ (this->*g)();} // ok
 //int l(){ ((*this).*A::g)();} // geht nicht
};

int main ()
{
 A foo;

 (foo.*(foo.g))(); // foo
}
//Suchbegriffe: function pointer funktion zeiger member functionpointer memberfunctionpointer[/code]

Benutzeravatar
pdreker
Beiträge: 8298
Registriert: 29.07.2002 21:53:30
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: Nürnberg

Beitrag von pdreker » 19.05.2003 21:00:07

weedy hat geschrieben:Schau dir doch mal den Kernelcode an.
Die Module füllen ganze Strukturen mit Funktionspointern
aus. bsp: ramfs/inode.c:
OK, das lasse ich gelten. Das ist aber
1) C und nicht C++ (in C sind fptr was nützliches, weil es keine elegante Ersatzmöglichkeit gibt, mir sind heute morgen noch Callbacks in C++ eingefallen, die auch nicht wirklich ganz ohne fptr klarkommen)
2) Das ist Kernelcode, man kann also nicht auf irgendwelche Luxus Funtionen zurückgreifen, sondern muss eh alles von Hand machen, das ganze nach Möglichkeit noch portabel auf 20 Architekturen und hardwarenah und schnell.
3) Kernelcode ist in diesem Zusammenhang ein schlechtes Beispiel. Da wimmelte es vor einiger Zeit noch vor "GOTO" Anweisungen (der Scheduler war die Hölle, der Original kommentar von Linus in dem Code lautete sinngemäss: "Dijkstra is going to hate me for this". Trotzdem käme ich nicht auf die Idee ausser in den absolut offensichtlichsten Fällen GOTO zu verwenden (early error exit + cleanup)).

Fazit1: Keine Regel ohne Ausnahme
Fazit2: In Userspace Anwendungen in C++ sind fptr normalerweise ein deutlicher Hinweis, dass die Klassenhierarchie noch nicht stimmt. In Ausnahmen siehe Fazit1.

Patrick
EOT
Definitely not a bot...
Jabber: pdreker@debianforum.de

Antworten