0
votes

I was trying to add a common base class to various CView items to simplify things but got weird results. Example Below:

Header:

#pragma once

class CParams;

class CCommonBase
{
  public:
  //virtual ~CCommonBase() {};

  virtual void DrawMyView(const CParams *params)=0;

};

class CMyView : public CEditView, CCommonBase
{
    DECLARE_DYNCREATE(CMyView)

    protected:
        CMyView();           // protected constructor used by dynamic creation
        virtual ~CMyView();

    public:
        virtual void DrawMyView(const CParams *params);
};

Code:

IMPLEMENT_DYNCREATE(CMyView, CEditView)

CMyView::CMyView()
{

}

CMyView::~CMyView()
{
}

void CMyView::DrawMyView(const CParams *params) {
  // ... do whatever ...
}

Example Usage in CTabView:

// have each view draw itself
CMFCTabCtrl &tabctrl=GetTabControl();
for(int i = 0;i < tabctrl.GetTabsNum();++i)
{
  CCommonBase *view=(CCommonBase*) tabctrl.GetTabWnd(i);
  if (view) {
   // This call ends up doing nothing but calling IMPLEMENT_DYNCREATE(CMyView, CEditView)
   view->DrawMyView(params);
    // Note: When virtual ~CCommonBase() {}; is not commented out the call above 
    // ends up calling the destructor which cases an MFC assert failure 
  }
}

The comment in the code above explains what happens. I can cast to the CMyView class and it works.

Is there a way to have a simple base class added to classes derived from MFC classes and use the base class to call the functions?

TIA!!

1

1 Answers

2
votes

As long as you use the hard C cast you have no chance. Use dynamic_cast

You force that the CWnd pointer returned by GetTabWnd is used as a CCommonBase, but it isn't. It is a CMyView.

By using dynamic_cast the internal derivations and vtables are checked. Required is that all classes have a virtual member.`

My advice: Never use the old cast syntax. Use dynamic_cast, static_cast and if not possible in another way reinterpret_cast