Verwirrende Pointer?

Nachtschwalbe

Grünschnabel
Hallo erstmal!

Bin neu hier und befinde mich seid ca 2 Monaten in meiner Ausbildung zum Fachinformatiker Anwendungsentwicklung. Habe in den ersten paar Wochen einige grundlegende Kentnisse zu C++ vermittelt bekommen unter linux mit dem KOMFORTABLEN VI editor :D

Nun ist aber .NET MFC angesagt. Hätte da mal Folgende Frage zu einem Kleinen Programmcode. Wenn man mit dem ProjektWizard ein MFC Projekt anlegt (Standarteinstellungen, also Multidoc etc...) dann werden ja Source Dateien vom Compiler selbst angelegt...

...und genau da versuche ich mich atm durchzuwühlen (Teilweise alles sehr unübersichtlich, bzw für mich noch nicht so gut nachvollziehbar. Neben der MainFrm.cpp wird ja auch eine .cpp Datei mit den Namen des Projektes angelegt, sagen wir einmal TestProjekt.cpp

Ich poste hier am besten nochmal den kompletten code dieser datei:

Code:
// StockChart.cpp : Defines the class behaviors for the application.
//

#include "stdafx.h"
#include "StockChart.h"
#include "MainFrm.h"

#include "ChildFrm.h"
#include "StockChartDoc.h"
#include "StockChartView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


// CStockChartApp

BEGIN_MESSAGE_MAP(CStockChartApp, CWinApp)
	ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
	// Standard file based document commands
	ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)
	ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)
	// Standard print setup command
	ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup)
END_MESSAGE_MAP()


// CStockChartApp construction

CStockChartApp::CStockChartApp()
{
	// TODO: add construction code here,
	// Place all significant initialization in InitInstance
}


// The one and only CStockChartApp object

CStockChartApp theApp;

// CStockChartApp initialization

BOOL CStockChartApp::InitInstance()
{
	CWinApp::InitInstance();

	// Standard initialization
	// If you are not using these features and wish to reduce the size
	// of your final executable, you should remove from the following
	// the specific initialization routines you do not need
	// Change the registry key under which our settings are stored
	// TODO: You should modify this string to be something appropriate
	// such as the name of your company or organization
	SetRegistryKey(_T("Addison Wesley Longman"));
	LoadStdProfileSettings(4);  // Load standard INI file options (including MRU)
	// Register the application's document templates.  Document templates
	//  serve as the connection between documents, frame windows and views
	CMultiDocTemplate* pDocTemplate;
	pDocTemplate = new CMultiDocTemplate(IDR_StockChartTYPE,
		RUNTIME_CLASS(CStockChartDoc),
		RUNTIME_CLASS(CChildFrame), // custom MDI child frame
		RUNTIME_CLASS(CStockChartView));
	AddDocTemplate(pDocTemplate);
	// create main MDI Frame window
	CMainFrame* pMainFrame = new CMainFrame;
	if (!pMainFrame->LoadFrame(IDR_MAINFRAME))
		return FALSE;
	m_pMainWnd = pMainFrame;
	// call DragAcceptFiles only if there's a suffix
	//  In an MDI app, this should occur immediately after setting m_pMainWnd
	// Enable drag/drop open
	m_pMainWnd->DragAcceptFiles();
	// Enable DDE Execute open
	EnableShellOpen();
	RegisterShellFileTypes(TRUE);
	// Parse command line for standard shell commands, DDE, file open
	CCommandLineInfo cmdInfo;
	ParseCommandLine(cmdInfo);
	// Dispatch commands specified on the command line.  Will return FALSE if
	// app was launched with /RegServer, /Register, /Unregserver or /Unregister.
	if (!ProcessShellCommand(cmdInfo))
		return FALSE;
	// The main window has been initialized, so show and update it
	pMainFrame->ShowWindow(m_nCmdShow);
	pMainFrame->UpdateWindow();
	return TRUE;
}



// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	enum { IDD = IDD_ABOUTBOX };

protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support

// Implementation
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()

// App command to run the dialog
void CStockChartApp::OnAppAbout()
{
	CAboutDlg aboutDlg;
	aboutDlg.DoModal();
}


// CStockChartApp message handlers

Teilweise bin ich ja schon dahintergestiegen was wo gemacht wird, in der Funktion InitInstance sind aber 2-3 Geschichten die mir noch etwas unklar sind: Erstmal wieder Code:

Code:
BOOL CStockChartApp::InitInstance()
{
	CWinApp::InitInstance();  <-Was geschieht hier? 
 ...
 ...
 ...
 ...
        CMainFrame* pMainFrame = new CMainFrame;
	if (!pMainFrame->LoadFrame(IDR_MAINFRAME))
		return FALSE;
	m_pMainWnd = pMainFrame;                             <---- 
	
	m_pMainWnd->DragAcceptFiles();                      <---- 

...
...
        pMainFrame->ShowWindow(m_nCmdShow);        <---- Warum pMainFrame?
	pMainFrame->UpdateWindow();
}

Also, pMainFrame ist ja ein pointer auf die CMainFrame Klasse und wird auf dem Heap instanziert, soweit so gut. Die darauffolgende IF Abfrage ist wohl soetwas wie eine Kollisionsabfrage auf einen Fehler beim Erstellen (denk ich mir jetzt mal so) Danach gehts los:

Code:
...
m_pMainWnd = pMainFrame;                             <---- 
...
m_pMainWnd->DragAcceptFiles();
...

Also halten wir das mal fest, an dieser Stelle wird die Speicherstelle auf die pMainFrame zeigt (Also die von CMainFrame) dem Pointer m_pMainWnd zugewiesen. m_pMainWnd ist ein Pointer aus CWinThread, der auf die Klasse CWnd zeigt:

Code:
....
CWnd* m_pMainWnd;
...

An dieser Stelle hat es bei mir zum ersten mal Knall gemacht, das sah für mich aus als ob
Man versucht 2 Pointer mit verschiedenen Typen (CMainFrame und CWnd) einander zuzuweisen. Bis ich etwas nachgeforscht habe: So wie es aussieht ist ist CWnd eine Oberklasse und die CMainFrame Klasse steht (an welcher Stelle auch immer) hirarchisch weit drunter und scheint von der Klasse CWnd zu erben, bzw im Zuge einer Vererbungskette zu erben. (so genau gecheckt hab ich das aber auch noch nicht)

OK! Dann versteh ich zumidnest warum es nicht knallt, aber warum zum geier wird denn in der Funktion im Quelltext mal mit dem einen Pointer und mal mit dem andern Pointer gearbeitet wenn doch beide auf das gleiche zeigen?
Nochmal der Code:

Code:
...
...
       m_pMainWnd = pMainFrame;                             
	
	m_pMainWnd->DragAcceptFiles();                      

...
...
        pMainFrame->ShowWindow(m_nCmdShow);      
	pMainFrame->UpdateWindow();
}

DAs ist eigentlich so mein Hauptproblem. Warum wird an der einen stelle mit m_pMainWnd gearbeitet und warum in der selben Funktion mit pMainFrame?

Hab ich irgendwo einen Logik Fehler, etwas nicht verstanden oder sind die von Billy Soft
einfach nur TOTAL INKONSEQUENT? :D

vielen dank für antworten hoffe auf eine rege diskussion
 
Die CMainFrame-Klasse wird ja für jedes Projekt individuell erstellt. Dort kannst du deinen eigenen Code einsetzen. Der MainFrame ist für ein MFC-Programm ein wichtiges Zentrum. Dieses muss von verschiedensten Stellen aus angesprochen werden. Diese Stellen sitzen im Standard-MFC-Code und kennen deine CMainFrame-Klasse nicht. Diese Stellen benutzen den Mainframe eigentlich nur wie ein normales Fenster. Daher wird dort einfach der kleinste gemeinsame Nenner benutzt, ein CWnd.

Die MFC so richtig zu durchblicken ist ziemlich heftig. Es gibt zwanzigtausend Stellen, an denen man nicht so ganz begreift warum und wieso etwas wie gemacht wird, es gibt aber dann normalerweise einen Grund. Der steht nur leider nicht in einem Kommentar daneben :)
 
Hi!
Danke dir erstmal für deinen Post :D

Versteh ich das jetzt richtig: die Oberklassen von MFC kennen mein CMainFrame nicht, und deswegen wird die Adresse des Pointers von CMainFrame dem Pointer von CWnd zugewiesen?

Das wär ja noch sinnvoll, erklärt mir aber immer noch nicht warum einmal der und einmal der pointer benutzt wird :(

Eventuell fehlt mir ja auch einfach ein wenig Nervennahrung und deswegen geh ich jetzt erstmal DEZENT nen DÖNER essen (Mittagspause :D)
 
Die Basisklassen von MFC sind ja fest in der DLL einkompiliert, die können deine CMainFrame-Klasse nicht kennen. Alle Dateien in deinem Ordner sind aber von MFC-Basisklassen abgeleitet, und können sich demzufolge auf deine CMainFrame beziehen (müssen die ja auch teilweise).

Tatsache ist, dass MFC auf den ersten kleinen Blick ordentlich strukturiert wirkt, auf den zweiten und dritten wie ein kompletter Sauhaufen und beim vierten wird dann doch wieder einiges klarer.
 
Zurück