4

I'm learning Visual C++ and building the "Sketcher" example program from Ivor Horton's Visual book, and I was able to generate the toolbars, menu icons, prompts, and a rectangle drawn with a few hard-coded points. After adding some mouse handlers and references to a few other header files, I receive this error: error C2011: 'CElement' : 'class' type redefinition.

Because of this "redefinition", there are 40+ errors thrown in the other shape classes that were previously based on CElement can't seem to find that class at compile time although the Visual Studio's intellisense seems to detect it just fine. I don't think I'm missing anything since everything compiled properly before my last few changes, but I've exhausted my undo/redo history and can't seem to find a root cause.

I've looked at some of the other answers related to this error message, but I'm still stuck on pinpointing exactly where my class is being defined a second time.

My Element.h file contains the following code:

#include <algorithm>
#include "stdafx.h"
class CElement : public CObject
{
protected:
    CPoint m_StartPoint; // Element position
    int m_PenWidth; // Pen width
    COLORREF m_Color; // Color of an element
    CRect m_EnclosingRect; // Rectangle enclosing an element

    // Create a pen
    void CreatePen(CPen& aPen);
public:
    virtual ~CElement();
    virtual void Draw(CDC* pDC) {} // Virtual draw operation
    // Get the element enclosing rectangle
    const CRect& GetEnclosingRect() const { return m_EnclosingRect; }
protected:
    // Constructors protected so they cannot be called outside the class
    CElement();
    CElement(const CPoint& start, COLORREF color, int penWidth = 1);
};

My Element.cpp file contains the following code:

#include "stdafx.h"
#include "Element.h"


CElement::CElement()
{
}

void CElement::CreatePen(CPen& aPen)
{
    if (!aPen.CreatePen(PS_SOLID, m_PenWidth, m_Color))
    {
        // Pen creation failed
        AfxMessageBox(_T("Pen creation failed."), MB_OK);
        AfxAbort();
    }
}

CElement::~CElement()
{
}

3 Answers3

4

Suggestion: use an include guard, in ALL of your header files:

Element.h:

#ifndef ELEMENT_H
#define ELEMENT_H

#include <algorithm>
#include "stdafx.h"

class CElement : public CObject
{
protected:
    CPoint m_StartPoint; // Element position
    ...
protected:
    // Constructors protected so they cannot be called outside the class
    CElement();
    CElement(const CPoint& start, COLORREF color, int penWidth = 1);
};

#endif
FoggyDay
  • 11,962
  • 4
  • 34
  • 48
  • Thank you for the suggestion and the reference. This solved the issue and taught me something not yet covered in the book or my classes. –  May 29 '16 at 06:46
3

as FoggyDay says you should avoid being re-included the class header.

Another easier way is just put "#pragma once" on the top of the header.

like

#pragma once

#include <algorithm>
#include "stdafx.h"
class CElement : public CObject
{
protected:
Jin
  • 704
  • 4
  • 11
2

You haven't shown enough code (even better, you would provide an MCVE) so it's hard to be certain.

However, the most likely explanation is that Element.h is being #included more than once in some compilation unit. This multiple inclusion may be indirect (e.g. the source file includes two (or more) different headers that each #include "Element.h"). The net result is that the compiler sees definitions of CElement more than once. Hence the error - such multiple definition in any compilation unit is illegal.

The usual solution is then to modify Element.h with include guards

#ifndef SOME_MACRO_UNIQUE_TO_YOUR_HEADER
#define SOME_MACRO_UNIQUE_TO_YOUR_HEADER

 //  the current content of the Element.h

#endif

The result of this is, when Element.h is #included more than once, that the definitions are not replicated.

Some folks will tell you to use #pragma once in the header. The problem with that approach is that it is specific to some compilers, but does not work with all compilers (even though it does with a number of compilers). Pragmas are a hook provided by the standard that enable compiler-specific extensions. Even worse, compilers that do not support #pragma once (or any other pragma for that matter) usually simply ignore them without issuing a diagnostic - because that is all the standard requires.

Peter
  • 35,646
  • 4
  • 32
  • 74
  • Thank you very much for this explanation. This helped my understanding a lot. –  May 29 '16 at 06:43