Frage zu C++
- weedy
- Beiträge: 585
- Registriert: 02.11.2002 21:47:49
- Lizenz eigener Beiträge: GNU General Public License
-
Kontaktdaten:
Frage zu C++
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.
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.
- pdreker
- Beiträge: 8298
- Registriert: 29.07.2002 21:53:30
- Lizenz eigener Beiträge: MIT Lizenz
- Wohnort: Nürnberg
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
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
Jabber: pdreker@debianforum.de
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
- weedy
- Beiträge: 585
- Registriert: 02.11.2002 21:47:49
- Lizenz eigener Beiträge: GNU General Public License
-
Kontaktdaten:
Danke. Das macht einen guten Eindruck.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
weedy.
- pdreker
- Beiträge: 8298
- Registriert: 29.07.2002 21:53:30
- Lizenz eigener Beiträge: MIT Lizenz
- Wohnort: Nürnberg
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
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
Jabber: pdreker@debianforum.de
- weedy
- Beiträge: 585
- Registriert: 02.11.2002 21:47:49
- Lizenz eigener Beiträge: GNU General Public License
-
Kontaktdaten:
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.
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.
- 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
//und die möchte ich euch jetzt nicht vorehthalten.
//los gehts:
//Suchbegriffe: function pointer funktion zeiger member functionpointer memberfunctionpointer[/code]
//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
}
- pdreker
- Beiträge: 8298
- Registriert: 29.07.2002 21:53:30
- Lizenz eigener Beiträge: MIT Lizenz
- Wohnort: Nürnberg
OK, das lasse ich gelten. Das ist aberweedy hat geschrieben:Schau dir doch mal den Kernelcode an.
Die Module füllen ganze Strukturen mit Funktionspointern
aus. bsp: ramfs/inode.c:
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
Jabber: pdreker@debianforum.de