Variable einer Klasse in einer anderen Klasse auswerten



  • Hi,

    ich habe 2 Klasse:

    Meine selbst erzeugte: HangmanWords
    und die von der MFC erzeugte CHangmandlg

    Eigenme Klasse

    class HangmanWords  
    {
    public:
    	CString ChosenWord;
    	HangmanWords();
    	virtual ~HangmanWords();
    private:
    	long zufall;
    	void GetWord();
    	CString Word[20];
    
    };
    

    mit

    void HangmanWords::GetWord()
    {
    	Word[0] = "Taschenrechner";
    	Word[1] = "Schulbibliothek";
    	Word[2] = "Maultasche";
    	Word[3] = "Neunmalklug";
    	Word[4] = "Programmierkenntnisse";
    	Word[5] = "Eintagsfliege";
    
        srand(5);
        zufall = rand();
    
    	ChosenWord = Word[zufall];
    }
    

    Wie kann ich den public-Wert ChosenWord jetzt in der vom MFC-Klassenassistenten erzeugten Klasse CHangmanDlg ChosenWord anwenden,
    so dass ich zum beispiel diese variable einem Textfeld zuweise

    z.B.
    m_strStaticChosenWord = ChosenWord;

    ich habs so probiert:
    m_strStaticChosenWord = HangmanWords::ChosenWord;

    gibt jedoch Fehlermeldungen 😞

    Hab bereits Stundenlang das cppTutorial durchsucht aber nichts geeignetes gefunden.

    Bitte um Hilfe 🙄

    Danke 👍

    Gruß mercer



  • mercer schrieb:

    Wie kann ich den public-Wert ChosenWord jetzt in der vom MFC-Klassenassistenten erzeugten Klasse CHangmanDlg ChosenWord anwenden,
    so dass ich zum beispiel diese variable einem Textfeld zuweise

    z.B.
    m_strStaticChosenWord = ChosenWord;

    ich habs so probiert:
    m_strStaticChosenWord = HangmanWords::ChosenWord;

    gibt jedoch Fehlermeldungen 😞

    Uuuuhh, da haperts aber mächtig an den Grundlagen! 😮

    Schaun wir uns das mal genauer an:

    m_strStaticChosenWord = HangmanWords::ChosenWord;
    

    1. HangmanWords ist der Name deiner Klasse, du musst von dieser Klasse erst ein Objekt (Instanz) erzeugen, damit du überhaupt damit arbeiten kannst. Die Klasse ist nur der "Bauplan", aber nichts konkretes. Also musst du erst mal so was in der Art in deinen Code einfügen:

    HangmanWords meineHangmanWorte;      //meineHangmanWorte ist nun dein Objekt
    

    2. Um auf (public-)Variablen eines Objekts zuzugreifen, musst du den Punkt-Operator verwenden, nicht den :: hier. Deine Zeile muss also richtig lauten:

    m_strStaticChosenWord = meineHangmanWorte.ChosenWord;
    

    Das ist zwar auch nicht optimal, es gäbe schönere Lösungen (get-Methoden und private-Variablen), aber erst einmal musst du das hier verstehen...
    Außerdem würde ich dir raten deine Variablen-Namen etwas übersichtlicher und konsequenter zu wählen, wenn du schon m_strStaticChosenWord schreibst, sollte die Variable deiner Klasse statt ChosenWord vielleicht m_strChosenWord heißen. Das ist aber eigentlich Geschmackssache... 😉

    Gruß Brainiac



  • Hm, Ok,
    irgendwie wills nicht??

    Ich hab meine eigene Klasse HangmanWords mit der Methode GetWords() und der öffentlichen Membervariablen ChosenWord (siehe oben)

    Jetzt dacht ich nach dem tollen Hinweis von Brainiac (danke dafür 👍 ),
    dass ich jetzt ein Objekt in der MFC - Klasse CHangmanDlg einschließe.

    Etwa so

    class CHangmanDlg : public CDialog
    {
    	[b]HangmanWords myWords;[/b]
    // Konstruktion
    public:
    
    	CHangmanDlg(CWnd* pParent = NULL);	// Standard-Konstruktor
    
    // Dialogfelddaten
    	//{{AFX_DATA(CHangmanDlg)
    	enum { IDD = IDD_HANGMAN_DIALOG };
    	CString	m_strChosenWord;
    	//}}AFX_DATA
    
    	// Vom Klassenassistenten generierte Überladungen virtueller Funktionen
    	//{{AFX_VIRTUAL(CHangmanDlg)
    	protected:
    	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV-Unterstützung
    	//}}AFX_VIRTUAL
    
    // Implementierung
    protected:
    	HICON m_hIcon;
    
    	// Generierte Message-Map-Funktionen
    	//{{AFX_MSG(CHangmanDlg)
    	virtual BOOL OnInitDialog();
    	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
    	afx_msg void OnPaint();
    	afx_msg HCURSOR OnQueryDragIcon();
    	afx_msg void OnEnd();
    	//}}AFX_MSG
    	DECLARE_MESSAGE_MAP()
    };
    

    Jetzt kommen einige Fehlermeldungen:
    error C2146: Syntaxfehler : Fehlendes ';' vor Bezeichner 'myWords'
    error C2501: 'HangmanWords' : Fehlende Speicherklasse oder Typbezeichner
    error C2501: 'myWords' : Fehlende Speicherklasse oder Typbezeichner

    was hab ich jetzt schon wieder verbrochen??

    Gruß
    mercer



  • Hat sich erledigt,
    hab vergessen die Klasse HangmanWords zu includieren. 🙄

    Aber wenn euch was auffällt oder ihr noch Vorschläge habt, immer her damit 👍

    Gruß
    mercer



  • Nochmal ich:

    So siehts bisher aus:

    MFC - Klasse

    class CHangmanDlg : public CDialog
    {
    	HangmanWords myWords;
    // Konstruktion
    public:
    
    	CHangmanDlg(CWnd* pParent = NULL);	// Standard-Konstruktor
    
    // Dialogfelddaten
    	//{{AFX_DATA(CHangmanDlg) ...
    

    Im OnInitDialog steht:

    // ZU ERLEDIGEN: Hier zusätzliche Initialisierung einfügen
    	MessageBox (myWords.ChosenWord);
    

    Meine eigene Klasse

    class HangmanWords  
    {
    public:
    	CString ChosenWord;
    	HangmanWords();
    	virtual ~HangmanWords();
    private:
    	long zufall;
    	void GetWord();
    	CString Word[20];
    
    };
    

    mit der Methode

    void HangmanWords::GetWord()
    {
    	Word[0] = "Taschenrechner";
    	Word[1] = "Schulbibliothek";
    	Word[2] = "Maultasche";
    	Word[3] = "Neunmalklug";
    	Word[4] = "Programmierkenntnisse";
    	Word[5] = "Eintagsfliege";
    
        srand(5);
        zufall = rand();
    
    	ChosenWord = Word[zufall];
    }
    

    nur wie bring ich das ganze jetzt zum laufen??
    Ist zwar fehlerlos aber es passiert nix 😮
    Muss ich da jetzt extra nen main Programm schreiben??

    Ich vermut mal, dass die Klasse HangmanWords gar nicht durchlaufen wird.
    Kann man das iergendwie hinbekommen ohne main??
    Sonst würde mein main sehr schnell sehr groß werden??

    Gruß
    omly a noop mercer



  • Moin,

    als aller erstes solltest Du Dir mal Grundkenntnisse über VC6 mit MFC(ich geh davon aus das Du das Benutzt) aneignen.

    1. Es gibt keine main Funktion, wenn dann nur eine winmain. Allerdings erstellt die das Studio für Dich.

    2. Die Funktion OnInitDialog wird schon durchlaufen bevor Dein Fenster erstellt wird. Schreibe statt (myWords.ChosenWord) einfach mal "Test" rein und starte Deine Anwendung, dann verstehst Du´s vielleicht was ich meine.
    (Das Fenster wird erst in OnPaint erstellt.)

    3. Solltest Du dann irgendwann so weit sein, dass Du Deine Variable einem Textfeld oder etwas ähnlichem zugewiesen hast, muß danach ein UpdateData(FALSE) erfolgen, sonst wird Dein Dialogfeld nicht aktualisiert.

    Gruß Sven



  • Außerdem mußt du irgendwo auch die Funktion getWord() (wieso ist die eigentlich private?) aufrufen, damit dein Zufallswort gefüllt werden kann.

    PS: Mit dem "srand(5);" deaktivierst du quasi den Zufallsgenerator - der bekommt bei jedem Aufruf den selben Seed und erzeugt deshalb jedes Mal die selbe Zufallszahl. Es reicht völlig aus, srand() einmal im Programm aufzurufen - und dann am besten mit einem Wert, der sich bei jedem Start ändert (z.B. "time(0)").

    PPS: Außerdem mußt du den Rückgabewert von rand() noch auf den Indexbereich deines Worte-Arrays runterskalieren - sonst erhältst du nur Datenmüll als Lösungswort.



  • Hallo,
    danke für die Tipps.

    Ich hab jetzt mal nen bissl rumprobiert und habs zum laufen gebracht.

    So siehts aus:

    OnInitDialog der MFC-Klasse

    // ZU ERLEDIGEN: Hier zusätzliche Initialisierung einfügen
    	m_strChosenWord = myGetWords.GetWord(3); //Anstatt 3 hier dann die Zufallszahl
    	UpdateData(FALSE);
    

    eigene Klasse:

    class HangmanWords  
    {
    public:
    	CString GetWord(int i);
    	//CString ChosenWord;
    	HangmanWords();
    	virtual ~HangmanWords();
    private:
    	//long zufall;
    	CString Word[20];
    
    };
    

    und die Get - Methode

    CString HangmanWords::GetWord(int i)
    {
    	Word[0] = "Taschenrechner";
    	Word[1] = "Schulbibliothek";
    	Word[2] = "Maultasche";
    	Word[3] = "Neunmalklug";
    	Word[4] = "Programmierkenntnisse";
    	Word[5] = "Eintagsfliege";
    
    	return Word[i];
    

    }
    mein Problem ist jetzt, ich find hier entsteht ein richtiges Dureinander...

    Ich glaube nicht das dies im Sinne der OOP ist???

    Eigentlich würde ich in der MFC-Klasse gerne nichts weiter tun außer Schnittstellen zu meiner Klasse zu erstellen und die Methoden, Variablen... der MFC-Klasse übergeben.

    Mit meiner Lösung müsste ich aber den Code zur zufallsgenerierung direkt in die MFC-Klasse schreiben was mir irgendwie gar nicht gefällt.

    Existiert da ne bessere Lösung??
    Und wenn ja, könnt mir die mal jemand zeigen??



  • Habs geschafft, war keine große Sache mehr...

    Hier mal die Übersicht

    #include "HangmanWords.h"
    class CHangmanDlg : public CDialog
    {
    //	HangmanWords myWords;
    	HangmanWords myGetWords;
    // Konstruktion
    public:
    
    	CHangmanDlg(CWnd* pParent = NULL);	// Standard-Konstruktor
    
    // Dialogfelddaten
    	//{{AFX_DATA(CHangmanDlg)
    	enum { IDD = IDD_HANGMAN_DIALOG };
    	CString	m_strChosenWord;
    	//}}AFX_DATA
    
    	// Vom Klassenassistenten generierte Überladungen virtueller Funktionen
    	//{{AFX_VIRTUAL(CHangmanDlg)
    	protected:
    	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV-Unterstützung
    	//}}AFX_VIRTUAL
    
    // Implementierung
    protected:
    	HICON m_hIcon;
    
    	// Generierte Message-Map-Funktionen
    	//{{AFX_MSG(CHangmanDlg)
    	virtual BOOL OnInitDialog();
    	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
    	afx_msg void OnPaint();
    	afx_msg HCURSOR OnQueryDragIcon();
    	afx_msg void OnEnd();
    	//}}AFX_MSG
    	DECLARE_MESSAGE_MAP()
    };
    

    Im OnInitDialog:

    // ZU ERLEDIGEN: Hier zusätzliche Initialisierung einfügen
    	m_strChosenWord = myGetWords.GetWord();
    	UpdateData(FALSE);
    
    class HangmanWords  
    {
    public:
    	CString GetWord();
    	//CString ChosenWord;
    	HangmanWords();
    	virtual ~HangmanWords();
    private:
    	int irand( int a, int e);
    	long zufall;
    	CString Word[20];
    
    };
    
    CString HangmanWords::GetWord()
    {
    	Word[0] = "Taschenrechner";
    	Word[1] = "Schulbibliothek";
    	Word[2] = "Maultasche";
    	Word[3] = "Neunmalklug";
    	Word[4] = "Programmierkenntnisse";
    	Word[5] = "Eintagsfliege";
    
    	zufall = irand(0,5);
    
    	return Word[zufall];
    
    }
    
    int HangmanWords::irand(int lowest, int highest)
    {
        //Aus nem Tutorial rauskopiert und angepasst
        srand((unsigned)time(0)); 
        int random_integer; 
        int range=(highest-lowest)+1; 
        for(int index=0; index<20; index++)
    	{ 
    		random_integer = lowest+int(range*rand()/(RAND_MAX + 1.0)); 
    	}
        return random_integer;
    }
    

    wer mal lust und zeit hat, kann das ja mal überfliegen und prüfen ob das vom Stil her i.O. geht.
    Wenn ich schon mit cpp anfange, wills ich ja gleich richtig lernen (die OOP).

    Nochmals danke an alle Antwortenden für die Tolle Hilfe

    Gruß
    mercer


Log in to reply