qq_41945416 2025-10-25 18:28 采纳率: 90.6%
浏览 6
已结题

关于使用类成员和mfc类构造函数传递变量的问题

1.1假如CADO是用户自定义mfc当中的一个类,用户调用成员函数或变量的时候能不能直接CADO::ADOInit(); 能不能直接CADO::m_error = S_OK;这样子调用可以吗?一定要声明成为对象才能调用吗?例如CADO a;a.ADOInit(); a.m_error = S_OK;
1.2 在mfc里 如果要利用构造函数传输数据,那就要重写构造函数,重写的时候要保留默认的构造函数,再重载新的构造函数吗?还是说将就之前的构造函数,直接在形参里填入需要的类或类型,源文件定义当中写需要的代码即可?
1.3 请看以下代码:

BOOL CMainWnd::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
    // TODO: 在此添加专用代码和/或调用基类
    m_wndsplitter.CreateStatic(CWnd::FromHandle(m_hWnd),3,1);
    m_wndsplitter.CreateView(0,0,RUNTIME_CLASS(CUSER1View),m_size,pContext);
    m_size.cy = (m_crect.Height() - m_size.cy) / 2;
    m_wndsplitter.CreateView(1,0,RUNTIME_CLASS(CUSER2View),m_size,pContext);
    m_size.cy = m_crect.Height() - 80 - m_size.cy;
    m_wndsplitter.CreateView(2,0,RUNTIME_CLASS(CUSER3View),m_size,pContext);
    return CFrameWnd::OnCreateClient(lpcs, pContext);
}

如上代码:CMainWnd 继承于CFrameWnd,在基于对话框项目 主对话框初始化的时候 通过 代码 :

CMainWnd * tmp_p = new CMainWnd(m1_crect);
tmp_p->Create(NULL,_T("APPVIEW"),WS_VISIBLE|WS_CHILD,m1_crect,CWnd::FromHandle(m_hWnd));

进行打开显示,m1_crect 是主对话框的成员变量 类为CRect 主要保存大小,m_wndsplitter和 m_size 是类CMainWnd 的成员变量 作用是分割器和大小 我现在已经通过CMainWnd 的构造函数 在new的时候把m1_crect的大小传给CMainWnd了,那我在OnCreateClient 创建了分割器 ,但问题是分割器需要的视图并不需要使用new CUSER1View(); 而是使用了 RUNTIME_CLASS(CUSER1View)来显示对应视图,1、2、3 视图中还要分别打开3个子对话框。m1_crect 很重要,这3个子对话框是要用到的 但没有办法用new操作符 那还怎么把m1_crect的值继续传递给CUSER1View呢?

  • 写回答

3条回答 默认 最新

  • 宝码香车 优质创作者: JavaScript技术领域 2025-10-25 19:11
    关注

    让【宝码香车】来帮您解答,本回答参考DeepSeek编写,并整理提供。

    如果答案让您满意,请采纳、点赞、关注,非常感谢!
    .
    每日一句正能量,让它带给您好心情:你值得拥有所有美好的东西,前提是你愿意为之努力。
    .

    1.1 关于类成员调用方式

    对于自定义类 CADO 的成员调用:

    不能直接使用 CADO::ADOInit()CADO::m_error = S_OK,除非这些成员被声明为 static

    正确的做法:

    // 头文件中的类定义
    class CADO {
    public:
        // 非静态成员函数
        void ADOInit();
        
        // 非静态成员变量
        HRESULT m_error;
        
        // 静态成员函数(如果需要直接调用)
        static void StaticADOInit();
        
        // 静态成员变量(如果需要直接调用)
        static HRESULT s_staticError;
    };
    
    
    // 使用方式
    CADO a;
    a.ADOInit();        // 正确:通过对象实例调用
    a.m_error = S_OK;   // 正确:通过对象实例访问
    
    
    // 如果是静态成员
    CADO::StaticADOInit();      // 正确:静态成员函数
    CADO::s_staticError = S_OK; // 正确:静态成员变量
    

    1.2 关于MFC构造函数重写

    在MFC中重写构造函数的最佳实践:

    // 头文件
    class CMyClass : public CWnd {
    public:
        // 保留默认构造函数
        CMyClass();
        
        // 重载带参数的构造函数
        CMyClass(CRect rect, CString strName);
        
        // 或者使用带默认参数的单一构造函数
        CMyClass(CRect rect = CRect(0,0,0,0), CString strName = _T(""));
        
    private:
        CRect m_rect;
        CString m_strName;
    };
    
    
    // 源文件实现
    CMyClass::CMyClass() {
        // 默认初始化
        m_rect = CRect(0,0,100,100);
        m_strName = _T("Default");
    }
    
    
    CMyClass::CMyClass(CRect rect, CString strName) {
        m_rect = rect;
        m_strName = strName;
    }
    

    推荐做法: 保留默认构造函数,同时重载带参数的构造函数。

    1.3 关于分割器视图传递数据的问题

    针对您的问题,有几种解决方案:

    方案1:通过文档类传递

    // 在CUSER1View中获取主窗口数据
    BOOL CUSER1View::OnCreate(LPCREATESTRUCT lpCreateStruct) {
        CView::OnCreate(lpCreateStruct);
        
        // 获取主框架窗口
        CMainWnd* pMainWnd = (CMainWnd*)AfxGetMainWnd();
        if (pMainWnd) {
            // 从主窗口获取矩形数据
            CRect mainRect = pMainWnd->GetMainRect();
            
            // 创建子对话框并传递数据
            CChildDialog1* pDlg = new CChildDialog1(this);
            pDlg->SetRectData(mainRect);
            pDlg->Create(IDD_CHILDDIALOG1, this);
            pDlg->ShowWindow(SW_SHOW);
        }
        
        return TRUE;
    }
    

    方案2:重写视图类的Create函数

    // 在CUSER1View类中添加
    class CUSER1View : public CView {
    public:
        BOOL Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, 
                    DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, 
                    CRect mainRect, UINT nID, CCreateContext* pContext = NULL) {
            m_mainRect = mainRect; // 保存主矩形
            return CView::Create(lpszClassName, lpszWindowName, dwStyle, 
                               rect, pParentWnd, nID, pContext);
        }
        
    private:
        CRect m_mainRect;
    };
    
    
    // 在CMainWnd::OnCreateClient中修改
    BOOL CMainWnd::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext) {
        m_wndsplitter.CreateStatic(CWnd::FromHandle(m_hWnd), 3, 1);
        
        // 创建视图时传递矩形数据
        m_wndsplitter.CreateView(0, 0, RUNTIME_CLASS(CUSER1View), m_size, pContext);
        
        // 获取创建的视图并设置数据
        CUSER1View* pView1 = (CUSER1View*)m_wndsplitter.GetPane(0, 0);
        if (pView1) {
            pView1->SetMainRect(m1_crect);
        }
        
        // 其他视图类似...
        return CFrameWnd::OnCreateClient(lpcs, pContext);
    }
    

    方案3:使用消息机制

    // 在视图类中添加消息处理
    BEGIN_MESSAGE_MAP(CUSER1View, CView)
        ON_MESSAGE(WM_USER_SET_RECT, OnSetRect)
    END_MESSAGE_MAP()
    
    
    // 在创建视图后发送消息
    BOOL CMainWnd::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext) {
        m_wndsplitter.CreateStatic(CWnd::FromHandle(m_hWnd), 3, 1);
        m_wndsplitter.CreateView(0, 0, RUNTIME_CLASS(CUSER1View), m_size, pContext);
        
        // 发送自定义消息传递矩形数据
        CUSER1View* pView1 = (CUSER1View*)m_wndsplitter.GetPane(0, 0);
        if (pView1) {
            pView1->SendMessage(WM_USER_SET_RECT, (WPARAM)&m1_crect);
        }
        
        // 其他视图...
        return TRUE;
    }
    
    
    // 在CUSER1View中处理消息
    LRESULT CUSER1View::OnSetRect(WPARAM wParam, LPARAM lParam) {
        CRect* pRect = (CRect*)wParam;
        if (pRect) {
            m_mainRect = *pRect;
            // 创建子对话框
            CreateChildDialogs();
        }
        return 0;
    }
    

    推荐使用方案2

    因为它最直接且符合MFC的设计模式,通过重写Create函数或提供设置函数来传递必要的数据。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 11月7日
  • 已采纳回答 10月30日
  • 修改了问题 10月25日
  • 创建了问题 10月25日