【问题标题】:C++ 'class' type redefinition errorC++“类”类型重新定义错误
【发布时间】:2016-09-27 03:43:43
【问题描述】:

我正在学习 Visual C++ 并从Ivor Horton's Visual book 构建“Sketcher”示例程序,我能够生成工具栏、菜单图标、提示和用一些硬编码点绘制的矩形。添加一些鼠标处理程序和对其他一些头文件的引用后,我收到此错误:error C2011: 'CElement' : 'class' type redefinition

由于这种“重新定义”,在以前基于 CElement 的其他形状类中引发了 40 多个错误,尽管 Visual Studio 的智能感知似乎可以很好地检测到它,但在编译时似乎无法找到该类。我认为我没有遗漏任何东西,因为在我最后几次更改之前所有内容都已正确编译,但我已经用尽了我的撤消/重做历史,似乎找不到根本原因。

我已经查看了与此错误消息相关的其他一些答案,但我仍然坚持要准确指出第二次定义我的类的位置。

我的 Element.h 文件包含以下代码:

#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);
};

我的 Element.cpp 文件包含以下代码:

#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()
{
}

【问题讨论】:

  • 你的 stdafx.h 包含什么?

标签: c++ visual-c++ compiler-errors header-files redefinition


【解决方案1】:

你没有展示足够的代码(更好的是,你会提供一个 MCVE),所以很难确定。

然而,最可能的解释是 Element.h 在某些编译单元中不止一次出现 #included。这种多重包含可能是间接的(例如,源文件包含两个(或更多)不同的标头,每个标头 #include "Element.h")。最终结果是编译器不止一次看到CElement 的定义。因此错误 - 在任何编译单元中的这种多重定义都是非法的。

通常的解决方案是使用包含防护来修改 Element.h

#ifndef SOME_MACRO_UNIQUE_TO_YOUR_HEADER
#define SOME_MACRO_UNIQUE_TO_YOUR_HEADER

 //  the current content of the Element.h

#endif

这样做的结果是,当 Element.h 多次为 #included 时,定义不会被复制。

有些人会告诉你在标题中使用#pragma once。该方法的问题在于它特定于某些编译器,但不适用于所有编译器(即使它适用于许多编译器)。 Pragmas 是标准提供的一个钩子,可以启用特定于编译器的扩展。更糟糕的是,不支持#pragma once(或任何其他编译指示)的编译器通常会直接忽略它们而不发出诊断 - 因为这就是标准所要求的。

【讨论】:

  • 非常感谢您的解释。这对我的理解很有帮助。
【解决方案2】:

正如 FoggyDay 所说,您应该避免重新包含类标题。

另一种更简单的方法是将“#pragma once”放在标题的顶部。

喜欢

#pragma once

#include <algorithm>
#include "stdafx.h"
class CElement : public CObject
{
protected:

【讨论】:

    【解决方案3】:

    建议:在所有头文件中使用include guard

    元素.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
    

    【讨论】:

    • 感谢您的建议和参考。这解决了这个问题并教会了我一些本书或我的课程中尚未涵盖的内容。
    猜你喜欢
    • 2014-11-01
    • 1970-01-01
    • 2019-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多