Zeiger auf Array als Rückgabe-Wert einer Funktion

Hallo, ich bin noch recht unerfahren was die Programmierung in C++ angeht und habe nun folgendes Problem:

Ich habe ein Objekt, das ein zweidimensionales char-Array als private-Attribut besitzt. Nun will ich eine getter-Methode in die Klassendefinition des Objekts schreiben, die es mir ermöglicht einen Zeiger auf dieses Array nach „außen“ zu geben. (Ich will von außen die Werte des Arrays auslesen können, aber nicht verändern.) Wie muss ich diese Methode aufbauen? Was für einen Rückgabe-Wert muss sie besitzen?

Mein Ansatz:
char* getFeld(){return feld;}

„feld“ ist der Name des Arrays und somit ja ein Zeiger da drauf, aber ich bekomme beim Kompilieren den Fehler, dass ‚char [40][40]‘ nicht in ‚char*‘ konvertiert werden kann. Wo liegt mein Fehler?

Danke im Voraus!
0nyx

Hallo 0nyx,

Ich habe ein Objekt, das ein zweidimensionales char-Array als
private-Attribut besitzt. Nun will ich eine getter-Methode in
die Klassendefinition des Objekts schreiben, die es mir
ermöglicht einen Zeiger auf dieses Array nach „außen“ zu
geben. (Ich will von außen die Werte des Arrays auslesen
können, aber nicht verändern.) Wie muss ich diese Methode
aufbauen? Was für einen Rückgabe-Wert muss sie besitzen?

Das hört sich ein wenig „java-esq“ an :wink:

Sowas kann man zwar in C machen, schön ist es aber
nicht. In C würde man anders an das Problem herangehen)

Folgender Quelltext veranschaulicht, wie man
ein 40x40 cont-char-Feld aus einer Funktion
zurückgibt (es geht in C nur über Zeiger):

#include 
#include 

 const char ( \*funktion\_gib\_array() ) [40][40]
{
 static char a\_versteckt[40][40];
 memset(a\_versteckt, 'A', sizeof(a\_versteckt));
 return &a\_versteckt;
}

 int main()
{
 int x,y;
 
 const char (\*array)[40][40];
 array = funktion\_gib\_array();
 
 for(y=0; yGrüße

CMБ

Hallo Semjon, danke für deine Antwort!

Das hört sich ein wenig „java-esq“ an :wink:

Ja, da liegst du gar nicht mal so falsch… zumindest habe ich davon ein bisschen mehr Ahnung.

Sowas kann man zwar in C machen, schön ist es aber
nicht.

Ja, ich weiß. Es ist nicht sehr elegant, aber für mein Vorhaben reicht das aus - vorausgesetzt ich bekomme es hin.

Leider verstehe ich deinen Quellcode zu wenig, um ihn in meinem Programm zu integrieren. Kannst du mir vielleicht grob erklären was da genau passiert und dabei folgendes beantworten:

  • Wieso wird der ‚*‘ im Funktionskopf an den Namen geklammert? Gehört dieser nicht zum ‚char‘? Was bewirkt die Klammerung? (sieht für mich wie ein Funktionszeiger aus)
  • An welcher Stelle im Funktionskopf muss ich ‚KlassenName::‘ unterbringen, wenn ich das ganze als externe Methode implementiere?
  • Was machen die Funktionen ‚memset()‘ und ‚putchar()‘?
  • Was bewirken die verschachtelten for-Schleifen in der main-Methode?

Fragen über Fragen, aber so ist das mit Anfängern :smile:
Vielleicht kannst du ein paar davon für mich beantworten.

MfG,
0nyx

Hallo Onyx,

Sowas kann man zwar in C machen, schön ist es aber
nicht.

Ja, ich weiß. Es ist nicht sehr elegant, aber für mein
Vorhaben reicht das aus - vorausgesetzt ich bekomme es hin.

Kannst Du Dein Vorhaben kurz
skizzieren, vielleicht gibt es
da ein „typisches“ C-Idiom,
welches man dann anwenden würde.

  • Wieso wird der ‚*‘ im Funktionskopf an den Namen geklammert?
    Gehört dieser nicht zum ‚char‘? Was bewirkt die Klammerung?
    (sieht für mich wie ein Funktionszeiger aus)

Das ist in C eine frage der „Präzedenz“,
da [] sehr „klebrig“ ist, muss man gegen
[] klammern, wenn man die „Klebrigkeit“
gerade nicht braucht.

Du nimmst z.B.:

 char \* zeiger [40][40];

Ohne Klammerung wäre das ein
2D-Array (40x40) von char*-Zeigern,
also:

 (char\*) (zeiger[40][40])
  • und nicht ein Zeiger auf ein Array
    von 40x40 char. Dagegen wäre

    char (*zeiger) [40][40];

genau das was Du brauchst.

Jetzt weisst Du auch, warum man
in Java die Reihenfolge geändert
hat :wink:

 char [][] arr = new char[40][40];
  • An welcher Stelle im Funktionskopf muss ich ‚KlassenName::‘
    unterbringen, wenn ich das ganze als externe Methode
    implementiere?

Was ist eine „externe Methode“? Ich kenne
Objektmethoden wie obj.method() und
statische Methoden wie CLASSNAME::Method()
letztere sind nicht an Objekte gebunden, erstere schon.

  • Was machen die Funktionen ‚memset()‘ und ‚putchar()‘?
  • Was bewirken die verschachtelten for-Schleifen in der
    main-Methode?

‚memset‘ füllt den angegebenen Speicherbereich
(hier das array) mit einem bestimmten Wert (‚A‘)
siehe -> http://www2.fh-fulda.de/~klingebiel/c-stdlib/string.htm

‚putchar‘ gibt einfach ein Zeichen auf
die Standardausgabe aus, also sowas
wie System.out.print( zeichen )
siehe --> http://www2.fh-fulda.de/~klingebiel/c-stdlib/stdio.htm

Schreib mal genauer, was Du eigentlich
vorhast :wink:

Grüße

CMБ

Hallo Semjon

Was ist eine „externe Methode“?

Also ich habe das so gelernt: Wenn man den Rumpf der Methode direkt in die Klassendefinition schreibt, dann handelt es sich um eine inline Methode. Schreibt man hingegen nur den Kopf der Methode in die Klasse und den Rumpf ausserhalb, dann handelt es sich um eine externe Methode (deshalb muss an dieser Stelle nochmal der Kopf mit ‚KlassenName::‘ vor dem Namen stehen).

Schreib mal genauer, was Du eigentlich
vorhast :wink:

Ich bin hier einfach an einer Programmieraufgabe für die FH dran. Ist nichts besonderes, sondern es geht einfach darum ein bisschen mit Klassen und Objekten zu spielen und ein paar Sachen auf die Konsole auszugeben.
Wie gesagt habe ich hier ein Objekt, dass das (zweidimensionale) char-Array als private-Attribut besitzt. Ich brauche nun außerhalb des Objekts die Werte des Arrays, um in Abhängigkeit davon bestimmte Methoden aufzurufen. Das Array soll private bleiben, deshalb brauche ich die genannte getter-Methode. Das Array ist also vorhanden - ich muss es in der getter-Methode nicht erst als static anlegen, sondern will „einfach“ einen Zeiger darauf nach außen zurückgeben.

Ich hoffe das ganze war jetzt nicht zu kompliziert erklärt… Solltest du es nicht verstanden haben, ist es auch egal - ich habe sowieso schon viel zu viel Zeit in diese Aufgabe investiert.

Mfg,
0nyx

Hallo 0nyx

Was ist eine „externe Methode“?

Also ich habe das so gelernt: Wenn man den Rumpf der Methode
direkt in die Klassendefinition schreibt, dann handelt es sich
um eine inline Methode. Schreibt man hingegen nur den
Kopf der Methode in die Klasse und den Rumpf ausserhalb, dann
handelt es sich um eine externe Methode (deshalb muss
an dieser Stelle nochmal der Kopf mit ‚KlassenName::‘ vor dem
Namen stehen).

Nicht ganz. Normalerweise erfolgt die
Klassenbildung in C++ so, dass man
die Memberfunktionen in der Klasse
deklariert und ausserhalb der Klasse
definiert (implementiert).

Davon abweichend gibt es die ‚inline definition‘,
und das wars bereits. man kann zwar den Unterschied
durch ‚externe definition‘ betonen, richtig ist das
aber nicht, da ‚extern‘ in C/C++ etwas ganz anderes
bedeutet: http://cplus.about.com/od/cprogrammin1/l/bldef_exter…

Wie gesagt habe ich hier ein Objekt, dass das
(zweidimensionale) char-Array als private-Attribut besitzt.
Ich brauche nun außerhalb des Objekts die Werte des Arrays, um
in Abhängigkeit davon bestimmte Methoden aufzurufen. Das Array
soll private bleiben, deshalb brauche ich die genannte
getter-Methode. Das Array ist also vorhanden - ich muss es in
der getter-Methode nicht erst als static anlegen, sondern will
„einfach“ einen Zeiger darauf nach außen zurückgeben.

Ach so. Trotzdem erschliesst sich mir der
Sinn nicht ganz, wozu das gut sein soll.
Nun ja, hier ein funktionierendes Beispiel.
(Fitzel Dich mal durch …)

 class ArrayClass { // Klassendefinition
 char c\_array[40][40]; // array member (private)
 public:

 const char( \*get\_array() const )[40][40] // Klassenmethode,
 { // inline-Methode (const), 
 return &c\_array; // implementation
 }

 char( \*get\_array() )[40][40]; // Klassenmethode, non-inline-
 }; // Methode, nur deklaration

 char( \*ArrayClass::get\_array() )[40][40] // Klassenmethode, 
{ // non-inline, 
 return &c\_array; // implementation 
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //

 void nimm\_const(const ArrayClass& ac)
{
 const char (\* a\_ptr) [40][40];
 a\_ptr = ac.get\_array(); // -\> const char( \*get\_array() const )[40][40]
}

 void nimm\_nonconst(ArrayClass& ac)
{
 char (\* a\_ptr) [40][40];
 a\_ptr = ac.get\_array(); // -\> char( \*ArrayClass::get\_array() )[40][40]
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //

 int main()
{
 ArrayClass ac;

 nimm\_nonconst( ac );
 nimm\_const( ac );

 return 0;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //

Grüße

CMБ

Hallo Semjon,

jetzt scheint es so zu klappen, wie ich mir das vorgestellt habe. Dadurch bin ich auf jeden Fall einen großen Schritt weiter.

Danke dir nochmal für alles!

MfG,
0nyx