Click here to Skip to main content
15,890,741 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
This is a portion of my code:

C++
template <class TBase, bool bCalcSize = true>
class COfficeBorder : public TBase
{
protected:

	virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
	{
		switch (message)
		{
		case WM_NCPAINT:
			{
				TBase::WindowProc(message, wParam, lParam);

				.
				.
				.

				return 0; // Handled.
			}

		case WM_CREATE:
			{
				if (TBase::WindowProc(message, wParam, lParam) == -1)
					return -1;

				.
				.
				.

				return 0; // Handled.
			}
			break;

		case WM_NCCALCSIZE:
			{
				LRESULT lResult = TBase::WindowProc(message, wParam, lParam);

				.
				.
				.

				return lResult;
			}
		}

		return TBase::WindowProc(message, wParam, lParam);
	}
};


The COfficeBorder works fine with CView, and any other controls:
C++
COfficeBorder<CView>
COfficeBorder<CEdit>
COfficeBorder<CStatic>


Except for CFormView
C++
COfficeBorder<CFormView>


I get the following errors when compiled:

VB
error C2512: 'COfficeBorder<class CFormView,1>' : no appropriate default constructor available
error C2614: 'CTest3View' : illegal member initialization: 'CFormView' is not a base or member


in the constructor:
C++
CTest3View::CTest3View()
    : CFormView(CTest3View::IDD)
{
    //{{AFX_DATA_INIT(CTest3View)
        // NOTE: the ClassWizard will add member initialization here
    //}}AFX_DATA_INIT
    // TODO: add construction code here

}


and the CTest3View class definition:

C++
class CTest3View : public COfficeBorder<CFormView>
{
protected: // create from serialization only
	CTest3View();
	DECLARE_DYNCREATE(CTest3View)

public:
	//{{AFX_DATA(CTest3View)
	enum{ IDD = IDD_TEST3_FORM };
		// NOTE: the ClassWizard will add data members here
	//}}AFX_DATA

// Attributes
public:
	CTest3Doc* GetDocument();

// Operations
public:

// Overrides
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CTest3View)
	public:
	virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	virtual void OnInitialUpdate(); // called first time after construct
	virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
	virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
	virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
	virtual void OnPrint(CDC* pDC, CPrintInfo* pInfo);
	//}}AFX_VIRTUAL

// Implementation
public:
	virtual ~CTest3View();
#ifdef _DEBUG
	virtual void AssertValid() const;
	virtual void Dump(CDumpContext& dc) const;
#endif

protected:

// Generated message map functions
protected:
	//{{AFX_MSG(CTest3View)
		// NOTE - the ClassWizard will add and remove member functions here.
		//    DO NOT EDIT what you see in these blocks of generated code !
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};


Any help here ?

Thank you for your understanding.
Posted
Updated 6-Jul-13 10:37am
v5
Comments
smss IR 6-Jul-13 17:35pm    
Try with use CFormView as a base class or a member of your own class.
smss IR 6-Jul-13 17:48pm    
And see this : http://msdn.microsoft.com/en-us/library/x49xah6k%28v=vs.80%29.aspx

1 solution

I think the error message is obvious: CFormView doesn't have a default constructor and because of this the automatically generated constructor of your COfficeBorder<CFormView> class has nothing to call. By the way, why COfficeBorder<CFormView> and not COfficeBorder<CTest3View>?

EDIT: Example code for template specialization:
C++
class ControlBase
{
protected:
	virtual void DoSomething() {}
};

class Control1 : public ControlBase
{
public:
	Control1() {}
};


class Control2 : public ControlBase
{
public:
	// no default constructor!!!
	Control2(int param) {}
};


class CommonHelpers
{
public:
	static void DoSomething(ControlBase* b)
	{

	}
};

template <typename BaseControl>
class ControlBorder : public BaseControl
{
protected:
	virtual void DoSomething() override
	{
		CommonHelpers::DoSomething(this);
	}
};

template <>
class ControlBorder<Control2> : public Control2
{
public:
	// We have to call one of the Control2 constructors explicitly because
	// Control2 does not have a default constructor!
	ControlBorder()
		: Control2(2)
	{}
protected:
	virtual void DoSomething() override
	{
		CommonHelpers::DoSomething(this);
	}
};
 
Share this answer
 
v2
Comments
Mr. Tomay 6-Jul-13 16:39pm    
I don't think so, I have added CTest3View class definition to the question
pasztorpisti 6-Jul-13 18:13pm    
If you want to use your template this way then you should create a specialization of your template for the CFormView class. The specialization can then have the necessary constructors for the CFormView class. Unfortunately the specialization must contain all the code from your current template but you can solve that by putting this wndproc handler code to a common place accessible by both templates (the current and the specialization).
pasztorpisti 6-Jul-13 18:23pm    
Updated my solution to include an example template specialization. If the specified window class doesn't have a default constructor then unfortunately you must handle that type (CFormView and in the example: Control2) with a template specialization that handles just that type!

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900