Ir ao conteúdo
  • Cadastre-se
Cambalinho

Como criar funções como em mfc?

Recommended Posts

verifique esta classe:

class test
{
public:
    virtual void output()
    {
      MessageBox(NULL,"hello world", "hi", MB_OK);
    }
};

test t;

void t::output()
{
    MessageBox(NULL,"hello world 2", "hi", MB_OK);
}

o C++ , parece, nao permitir fazer 'void t::output()', se nao ter a declaraçao na classe.

em MFC ao criar objectos eu posso usar o operador scope resolution(::) para alterar 1 evento. em Code Blocks eu nao nao posso fazer eventos que usem o operador '::'. mas alguem me pode dar alguma dicas sobre isto?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Acho que não hein O.o Pense bem... Para que serviria isso se fosse possível faze-lo? De que serve mudar a utilidade de uma função membro fora de uma herança? Não faz sentido isso. Pode evidenciar um caso mais concreto no qual mfc permite isso? Digo isso porque uma função virtual não permite ser modificada fora da classe. Se essa função estivesse dentro de uma classe que tivesse recebido hipoteticamente falando por herança a essa classe test, então você poderia reescrever esse método da superclasse dentro da subclasse, não sei se me faço entender.

Editado por vangodp

Compartilhar este post


Link para o post
Compartilhar em outros sites

pois mas 1 funçao virtual tem de ser declarada numa subclasse.

a minha ideia é mais simples do que pensas... eu quero usar '::' como fosse para programar os eventos. eu tenho 1 forma, mas é como variaveis e nao posso alterar 1 variavel na secçao Global.

eu posso te dar 1 codigo que queria que fosse valido, mas claro que iria ter alguns erros

Compartilhar este post


Link para o post
Compartilhar em outros sites

manda ele para eu fazer uma ideia do que você quer. A ver se entendo o que você está buscando. Se possível comente.

Compartilhar este post


Link para o post
Compartilhar em outros sites

see these sample:

class test
{
    public: EVENT void message()//eu usei 'EVENT'... o objectivo é como fosse para isso. ou 1 tipo de funáo que nao precisa de decalaraçao nos objectos, mas que possa se mudada de objecto para objecto
    {
        MessageBox(NULL, "hello world", "hi", MB_OK);
    }
};

test a;

void a::message()//como ves, esta funçao nao foi declarada no objecto 'a'
{
    MessageBox(NULL, "hello world", "hi 'a'", MB_OK);
}

eu sei que o C++ nao permite subscrever o operador Scope '::'... mas talvez possa fazer isto de forma diferente

Compartilhar este post


Link para o post
Compartilhar em outros sites

Na verdade não tenho nem ideia se isso é possivel, porém o mais parecido que posso lhe indicar é o tal "recorte de objetos" que podemos ver aqui: Virtual Functions Object Slicing. Basicamente se trata de ter varias classes base na qual podemos usar o ponteiro da superclasse para acessar a qualquer uma das subclasses. Logicamente cada função message() seria polimorfica. Um exemplo poderia ser:

#include <iostream>
#include <windows.h>
using namespace std;

class A {

public:
    virtual void msg() { MessageBox(NULL, "hello world1", "hi 'a'", MB_OK); }
};

class B: public A {

public:
    virtual void msg() { MessageBox(NULL, "hello world2", "hi 'b'", MB_OK); }
};

class C: public B {

public:
    virtual void msg() { MessageBox(NULL, "hello world3", "hi 'c'", MB_OK); }
};


main() {
    A *ptr1 = new C();
    
    (*ptr1).msg();
}

O segredo é a linha  A *ptr1 = new C();. Como podemos ver ptr1 é claramente do tipo A, porém eu lhe atribuo um objeto dinâmico do tipo C, o efeito é que ptr1 aponta a um objeto do tipo C, mesmo ainda sendo do tipo A. Eu também poderia faze-lo apontar para um objeto do tipo B, etc, e nesse caso me mostraria o mensagem  "hello world2". A regra é que você tem que atribuir de forma dinâmica, se fazer de forma não dinâmica(A a = C();) você recortará as subclasses, por isso o nome recorte de objetos, nesse caso a mensagem seria "hello world1", por isso a importância do new na operação. Isso tudo tem que ver com uma tabela blablabla de VPTRs etcetc(google >_<).

Não sei se lhe interessa mas...

Tente dar uma olhada nas bibliotecas MFC a ver como estão implementadas. O mais certo é que seja uma DLL e você não possa dar uma olhada ja que nossa grande amiga microsoft é tão fechada >_<.

Editado por vangodp

Compartilhar este post


Link para o post
Compartilhar em outros sites

como ves: de classe para classe temos de declarar a 'msg'.

mas ainda nao resolveu a minha questao :(

será que consigo ter acesso a 1 classe MFC?

(tenho VS98 instalado)

Compartilhar este post


Link para o post
Compartilhar em outros sites

vê este exemplo:

afx_msg void OnDestroy();

fui o buscar: https://msdn.microsoft.com/en-us/library/1xb05f0h.aspx#cwnd__onactivate

então fui pesquisar afx_msg: https://msdn.microsoft.com/en-us/library/aa235256(v=vs.60).aspx

mas não consigo entender :(

 

adicionado 56 minutos depois

desculpa mas ve outro exemplo:

class events
{
    public:  void click()
    {
        MessageBox(NULL, "click 1","hi", MB_OK);
    }
};

class a: public events{};

void a::click()
{
    MessageBox(NULL, "hello 1","hi", MB_OK);
}

erro: "no 'void a::click()' member function declared in class 'a'".

yah quer me obrigar a fazer 1 declaraçao na classe 'a'.... mesmo derivada da 'events'

Compartilhar este post


Link para o post
Compartilhar em outros sites

você não seteou click como virtual na classe mãe. Quando tiver tempo dou uma olhada no resto, to meio ocupado esses dias e não sobra muito tempo.

adicionado 7 minutos depois

Para não deixar no vaco só digo que busque saber como está declarado a classe CAboutDlg, aí é onde reside o truque da bagaça. ;)

Compartilhar este post


Link para o post
Compartilhar em outros sites

nao encontro nd que me ajude alem:

virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);

ou

afx_msg void OnContextHelp(); 

ou

//CFrameWnd é o nome da classe

//{{AFX_MSG(CFrameWnd)
	// Windows messages
	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
	afx_msg void OnDestroy();
	afx_msg void OnClose();
	afx_msg void OnInitMenu(CMenu*);
	afx_msg void OnInitMenuPopup(CMenu*, UINT, BOOL);
	afx_msg void OnMenuSelect(UINT nItemID, UINT nFlags, HMENU hSysMenu);
	afx_msg LRESULT OnPopMessageString(WPARAM wParam, LPARAM lParam);
	afx_msg LRESULT OnSetMessageString(WPARAM wParam, LPARAM lParam);
	afx_msg LRESULT OnHelpPromptAddr(WPARAM wParam, LPARAM lParam);
	afx_msg void OnIdleUpdateCmdUI();
	afx_msg void OnEnterIdle(UINT nWhy, CWnd* pWho);
	afx_msg void OnSetFocus(CWnd* pOldWnd);
	afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
	afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
	afx_msg void OnSize(UINT nType, int cx, int cy);
	afx_msg BOOL OnEraseBkgnd(CDC* pDC);
	afx_msg void OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized);
	afx_msg BOOL OnNcActivate(BOOL bActive);
	afx_msg void OnSysCommand(UINT nID, LONG lParam);
	afx_msg BOOL OnQueryEndSession();
	afx_msg void OnEndSession(BOOL bEnding);
	afx_msg void OnDropFiles(HDROP hDropInfo);
	afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
	afx_msg LRESULT OnCommandHelp(WPARAM wParam, LPARAM lParam);
	afx_msg LRESULT OnHelpHitTest(WPARAM wParam, LPARAM lParam);
	afx_msg LRESULT OnActivateTopLevel(WPARAM wParam, LPARAM lParam);
	afx_msg void OnEnable(BOOL bEnable);
	afx_msg void OnPaletteChanged(CWnd* pFocusWnd);
	afx_msg BOOL OnQueryNewPalette();
	// standard commands
	afx_msg BOOL OnToolTipText(UINT nID, NMHDR* pNMHDR, LRESULT* pResult);
	afx_msg void OnUpdateKeyIndicator(CCmdUI* pCmdUI);
	afx_msg void OnHelp();
	afx_msg void OnUpdateContextHelp(CCmdUI* pCmdUI);
	//}}AFX_MSG
protected:
	afx_msg LRESULT OnDDEInitiate(WPARAM wParam, LPARAM lParam);
	afx_msg LRESULT OnDDEExecute(WPARAM wParam, LPARAM lParam);
	afx_msg LRESULT OnDDETerminate(WPARAM wParam, LPARAM lParam);
	afx_msg LRESULT OnRegisteredMouseWheel(WPARAM wParam, LPARAM lParam);
	DECLARE_MESSAGE_MAP()

nao vejo nada util, porque nao temos as livrarias afx... mesmo assim penso que afx_msg é para gerar  mais codigo que nao vemos.

Compartilhar este post


Link para o post
Compartilhar em outros sites
1 hora atrás, Cambalinho disse:

virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);

O virtual é o que permite ser modificado. Os outros não revelam nada

Compartilhar este post


Link para o post
Compartilhar em outros sites
class events
{
    public:  void click()
    {
        MessageBox(NULL, "click 1","hi", MB_OK);
    }
};

class a: public events{};

void a::click()
{
    MessageBox(NULL, "hello 1","hi", MB_OK);
}

erro: a funçao 'click' nao esta declarada em 'a'. então imagina se 'a' é 1 objecto do events.... yah é aqui que esta o problema.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Ao parecer seu motivo de revolta >_< é saber porque deve declarar click na classe derivada. É isso? Bom vou lhe dizer porque você está obrigado a declarar click mesmo recebendo a classe events por herança, e a resposta é simples. você está reescrevendo uma nova função! Não se trata da mesma que função. Para que esse mecanismo funcione você tem que seguir uns quantos passos. O 1º passo é indicar na classe base que click é virtual, isso quer dizer que cada classe derivada pode conter o click modificado(reescrito).
2º você está obrigado a declarar a função click dentro da classe base se for modificar o método.


Vamos ver um exemplo:
 

#include <iostream>
#include <windows.h>
#include "processo.h"
using namespace std;

//classe base
class A {
public:
    //1º Declarar click como virtual dentro da classe base
    virtual void click() {
        MessageBox ( NULL, "click 1", "hi", MB_OK );
    }
};

//classe derivada
class B: public A {
public:
    //2º Se for modificar click dentro da classe derivada você deve redeclarar click, não é obrigatorio por virtual porém se quiser por não ha problema algum
    virtual void click();
};

//Agora ja pode modificar a função sem problemas, essa função "pisa"(reescreve) a função click da classe base.
void B::click() {
    MessageBox ( NULL, "hello 1", "hi", MB_OK );
}


int main() {

    B b;
    
    b.click();

    return 0;
}

 

você deve se estar perguntando porque tem que redeclarar, porque eu ainda não expliquei o motivo, e é que o motivo é uma 3º clausura.


3º Se quiser acessar ao método da classe base desde a classe derivada você precisa usar o Operador de resolução do escopo (::)
Vamos ver um exemplo:
 

#include <iostream>
#include <windows.h>
#include "processo.h"
using namespace std;

//classe base
class A {
public:

    virtual void click() {
        MessageBox ( NULL, "click 1", "Base", MB_OK );
    }
};

//classe derivada
class B: public A {
public:
    virtual void click();
};


void B::click() {
    //E aqui o motivo pelo qual você deve declarar click na classe base. O motivo é que podemos 
    //invocar o metodo click da classe base dentro da classe derivada
    A::click();
    
    // reescrevendo o metodo click
    MessageBox ( NULL, "click 2", "Derivada", MB_OK ); 
}


int main() {

    B b;
    
    b.click();
    
    

    return 0;
}

E por isso você está obrigado a redeclarar o método click na classe derivada, porque na realidade tratasse de outro metodo click reescrito. A prova é que você pode invocar ao método click da classe base dentro do método click da classe derivada. Suponho que internamente tudo é feito com ponteiros, quando você define uma nova click dentro da classe derivada, nesta classe o ponteiro que indica onde esta a função click começa a apontar ao click que foi reescrito que é o desejado ja que foi reescrito para essa finalidade.^_^ Agora são só suposições o que acabo de falar sobre os mecanismos internos, mas dentro de uma classe todos sabemos que existem coisas ocultas como as vtable, o ponteiro this, e assim vai. Se quiser saber mais sobre o mecanismo interno das classes busque documentação sobre herança.

Espero ter ajudado.

  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

sim isso me irrita e muito. então imagina se 'B' fosse 1 objecto.. pior ainda.

estou a pensar numa coisa, mas para testar tenho de resolver 1 problema na instalação do VS6 no windows 7.

talvez, com 1 DLL, eu consiga transferir o 'afx_msg' do MFC para o C++... claro que é só 1 ideia.

Compartilhar este post


Link para o post
Compartilhar em outros sites

ja consegui instalar o VS6. mas preciso de ajuda para criar 1 DLL que me permite usar os eventos:

// addin.cpp : Defines the entry point for the DLL application.
//

#include "stdafx.h"


class test
{
	//{{AFX_MSG(test)
	// Windows messages
	afx_msg void hello();
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP();

	
	
};

class test2: public test{};

void test2::hello()
{
	MessageBox(NULL,"hello world2", "hi", MB_OK);
}

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
					 )
{
    return TRUE;
}

eu nunca usei o afx, por isso tenho muitos erros.

podes me ajudar a resolver os erros?

(quero, no fim, usar a dll no GCC\GNU)

erro: "'afx_msg' : missing storage-class or type specifiers"

Compartilhar este post


Link para o post
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisar ser um membro para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora





Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas publicações sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×