2

I have a project which I'm migrating from VC6 to VS2013. While I was building the project, I'm getting this error.

error LNK2005: "public: virtual __thiscall CMemDC::~CMemDC(void)" (??1CMemDC@@UAE@XZ) already defined in GameBoard.obj

Following are the files that might be creating this issue.

GameBoard.h

#include "DirectSound.h"
#include "MIDI.h"
#include <vector>
class CGameBoard : public CWnd
{
    friend class CTetrisDlg;
    friend class COptionsDlg;

    DECLARE_DYNAMIC(CGameBoard);

// Construction/Destruction
public:
    CGameBoard();
    virtual ~CGameBoard();

.......
};

GameBoard.cpp file has definition for this destructor.

#include "stdafx.h"
#include "Tetris.h"
#include "GameBoard.h"
#include "Piece.h"
#include "MemDC.h"
#include "VolumeCtrl.h"

#include <stdlib.h>
#include <time.h>
static CGameBoard * gpGameBoard;

CGameBoard::CGameBoard()
{
    m_pCurPiece = m_pNextPiece = 0;
    m_usLevel = 0;
    m_clrCurPiece = RGB(0,0,0);
    m_bShowGrid = TRUE;
    m_nSquareWidth = 14;
    m_nSquareHeight = 14;
    m_clrBackground = RGB(255, 255, 255);
    m_bExFigures = FALSE;
    m_pMusic = 0;
    m_uTimer = 0;
    m_dwVolume = 100;   // 100% music volume by default

    gpGameBoard = this;
}

CGameBoard::~CGameBoard()
{
    if(m_pCurPiece)
        delete m_pCurPiece;
    if(m_pNextPiece)
        delete m_pNextPiece;

    if( m_pMusic )
        delete m_pMusic;

    gpGameBoard = 0;
}

This destructor is defined only once in GameBoard.cpp and GameBoard is not included in any other cpp or header file.

MemDC.h

#ifndef _MEMDC_H_
#define _MEMDC_H_

class CMemDC : public CDC {
private:
    CBitmap m_bitmap;       // Offscreen bitmap
    CBitmap* m_oldBitmap;   // bitmap originally found in CMemDC
    CDC* m_pDC;             // Saves CDC passed in constructor
    CRect m_rect;           // Rectangle of drawing area.
    BOOL m_bMemDC;          // TRUE if CDC really is a Memory DC.

public:
    CMemDC(CDC* pDC) : CDC(), m_oldBitmap(NULL), m_pDC(pDC)
    {
        ASSERT(m_pDC != NULL); // If you asserted here, you passed in a NULL CDC.

        m_bMemDC = !pDC->IsPrinting();

        if (m_bMemDC){
            // Create a Memory DC
            CreateCompatibleDC(pDC);
            pDC->GetClipBox(&m_rect);
            m_bitmap.CreateCompatibleBitmap(pDC, m_rect.Width(), m_rect.Height());
            m_oldBitmap = SelectObject(&m_bitmap);
            SetWindowOrg(m_rect.left, m_rect.top);
        } else {
            // Make a copy of the relevent parts of the current DC for printing
            m_bPrinting = pDC->m_bPrinting;
            m_hDC = pDC->m_hDC;
            m_hAttribDC = pDC->m_hAttribDC;
        }
    }

    ~CMemDC()
    {
        if (m_bMemDC) {
            // Copy the offscreen bitmap onto the screen.
            m_pDC->BitBlt(m_rect.left, m_rect.top, m_rect.Width(), m_rect.Height(),
                            this, m_rect.left, m_rect.top, SRCCOPY);
            //Swap back the original bitmap.
            SelectObject(m_oldBitmap);
        } else {
            // All we need to do is replace the DC with an illegal value,
            // this keeps us from accidently deleting the handles associated with
            // the CDC that was passed to the constructor.
            m_hDC = m_hAttribDC = NULL;
        }
    }

    // Allow usage as a pointer
    CMemDC* operator->() {return this;}

    // Allow usage as a pointer
    operator CMemDC*() {return this;}
};

#endif

This problem is related to One Definition Rule which is defined here, but I'm not getting what to do.

I have done some changes suggested here. And now I'm getting following error. Any idea, pls?

error LNK1181: cannot open input file 'Nafxcwd.lib Libcmtd.lib'

Amnesh Goel
  • 2,617
  • 3
  • 28
  • 47
  • 2
    The error refers to `CMemDC::~CMemDC(void)` not the destructor of `GameBoard`. Are you perhaps missing an include guard somewhere? – odyss-jii Aug 14 '15 at 11:26
  • @odyss-jii **Include guard* -- include statements? added for reference pls. – Amnesh Goel Aug 14 '15 at 11:29
  • Doesn't it say anything about which other file that defines the destructor? – skyking Aug 14 '15 at 11:32
  • You haven't posted the relevant source. The problem is with `CMemDC` destructor. – skyking Aug 14 '15 at 11:34
  • @skyking No it doesn't say anything. I checked for the destructor definition in other files, but it doesn't exist. I have added constructor definition for reference, pls. – Amnesh Goel Aug 14 '15 at 11:34
  • Can you post `CMemDC` source? – Nishant Aug 14 '15 at 11:36
  • Why don't to put header guard in your header file? – Paani Aug 14 '15 at 11:37
  • Include guards ensure that the code in header is not included/parsed/compiled more than once during compilation, which would otherwise lead to multiple re-definitions of the same things. Typically, it is done by introducing preprocessor variable for each file: `FILE_NAME_H`, which is set when file is processed, and checked every time before processing. Wrap body of header in preprocessor if-not-defined clause: `#ifndef FILE_NAME_H`, followed by `#define FILE_NAME_H`, then include the body of the header, and finally `#endif`. – odyss-jii Aug 14 '15 at 11:38
  • According to MSDN the error should look something like `oledb.lib(oledb_i.obj) : error LNK2005: _IID_ITransactionObject already defined in uuid.lib(go7.obj)`, the offending object file (`oledb_i.obj) is clearly identified as well as the other file (`go7.obj`). Are you sure that this is not shown in your error message? – skyking Aug 14 '15 at 11:48
  • pls check this.. Error 7 error LNK2005: "public: virtual __thiscall CMemDC::~CMemDC(void)" (??1CMemDC@@UAE@XZ) already defined in GameBoard.obj D:\MFC projects\CGTetris11src\nafxcwd.lib(afxglobals.obj) – Amnesh Goel Aug 14 '15 at 11:49
  • Have you tried to disable precompiled headers? Maybe your source doesn't conform to the restrictions needed for them to work. – skyking Aug 14 '15 at 11:53
  • I disabled them, but no luck @skyking – Amnesh Goel Aug 14 '15 at 11:56
  • It may be the nafxcwd.lib that's causing problems, maybe the same as this: http://stackoverflow.com/questions/1146338/error-lnk2005-new-and-delete-already-defined-in-libcmtd-libnew-obj – skyking Aug 14 '15 at 12:00
  • I checked the link but I don't understand how it is related to this problem @skyking – Amnesh Goel Aug 14 '15 at 12:07
  • I still think that you have not posted the **complete** error output from the linker, that would help diagnosing the problem. BTW have you checked by googling for `nafxcwd.lib` linking problems? – skyking Aug 14 '15 at 12:12
  • Maybe a clash with the existing CMemDC: https://msdn.microsoft.com/en-us/library/cc308997(v=vs.90).aspx –  Aug 14 '15 at 12:26
  • So @DieterLücking I shoudn't be using CMemDC class? But when I removed that class from **GameBoard.cpp*, then I had n number of errors. Pls help. – Amnesh Goel Aug 14 '15 at 12:32
  • A number of errors? But you have only posted one, how do you think we should be able to help you if you don't post the errors? I still think you've left some important parts of the errors out. – skyking Aug 15 '15 at 13:35

3 Answers3

1

Well finally following settings helped me to fix this problem..

  1. Project properties->linker->input->ignore specific default library .. set to .. nafxcw.lib libcmt.lib
  2. Project properties->c/c++->Code generation->run time library .. set to .. Multi threaded DLL (/MD)
  3. Project properties->configuration properties->general->Use of MFC .. set to .. use of MFC in a shared DLL.

And apart from these settings, I didn't change anything in code (w.r.t. include guards etc.)

Amnesh Goel
  • 2,617
  • 3
  • 28
  • 47
0

You haven't provided complete code. But in general it seems your code lacks header guards. These are necessary and without them you most likely end up in linker issues like yours.

On windows add this line at top in all your header files:

#pragma once

In general you can use the traditional header guard across all compilers

#ifndef HEADERNAME_H
#define HEADERNAME_H

//Put content of header file here

#endif
Paani
  • 560
  • 3
  • 11
0

I had the same problem with some old code just recently. I thought it was odd that I was also seeing errors with a class called CMemDC that was defined in my code. I renamed the class CMemJBDC and the error went away.

John
  • 1
  • 1