【问题标题】:'Render': 'class' type redefinition (C2011)“渲染”:“类”类型重新定义(C2011)
【发布时间】:2018-01-20 20:38:53
【问题描述】:

关于这个话题,Stack Overflow 上有很多类似的问题。

我正在创建一个包含多个文件(.cpp 和 .h)的项目。我收到错误消息:

C2011: 'Render': 'class' 类型重新定义

我已经阅读过它。有人说使用警卫,所以我在所有头文件上使用#pragma once。有人说标题被多次包含,但守卫会阻止这种情况。那我做错了什么?

代码:

Cubes.h

#pragma once

char orientation(int sides, int hV);

std::vector<char> visOrd(std::string *xOrd, int *pov, int ord);

std::vector<int> convertColour(std::vector<std::string> rlBoxCol);

std::tuple<std::vector<int>, std::vector<std::string>> organiseLayers(std::vector<int> boxCoords, std::vector<std::string> rlBoxCol, std::vector<float> rot);


class Render
{
private:
    std::vector<float> rot;
    std::vector<int> boxCoords;
    std::vector<std::string> rlBoxCol;
    int gridSize;
    int cubeSize;
    std::vector<int> offset;

public:
    Render();


    void setRotation(std::vector<float> setRot);
    std::vector<float> getRotation();

    void setCoordinates(std::vector<int> setBoxCoords);
    std::vector<int> getCoordinates();

    void setColours(std::vector<std::string> setRlBoxCol);
    std::vector<std::string> getColours();

    void setSizeOfGrid(int setGridSize);
    int getSizeOfGrid();

    void setSizeOfCubes(int setCubeSize);
    int getSizeOfCubes();

    void setOffset(std::vector<int> setOffset);
    std::vector<int> getOffset();


    void display();
};

Cubes.cpp

#include "Cubes.h"
#include "Global.h"

char orientation(int sides, int hV)
{
// Code
}

std::vector<char> visOrd(std::string *xOrd, int *pov, int ord)
{
// Code
}


std::vector<int> convertColour(std::vector<std::string> rlBoxCol)
{
// Code
}

std::tuple<std::vector<int>, std::vector<std::string>> organiseLayers(std::vector<int> boxCoords, std::vector<std::string> rlBoxCol, std::vector<float> rot)
{
// Code
}



Render::Render()
{
    this->rot;
    this->boxCoords;
    this->rlBoxCol;
    this->gridSize;
    this->cubeSize;
    this->offset;
}


void Render::setRotation(std::vector<float> setRot)
{ // Set rotation
    rot = setRot;
}
std::vector<float> Render::getRotation()
{ // Get rotation
    return rot;
}

void Render::setCoordinates(std::vector<int> setBoxCoords)
{
    boxCoords = setBoxCoords;
}
std::vector<int> Render::getCoordinates()
{
    return boxCoords;
}

void Render::setColours(std::vector<std::string> setRlBoxCol)
{
    rlBoxCol = setRlBoxCol;
}
std::vector<std::string> Render::getColours()
{
    return rlBoxCol;
}

void Render::setSizeOfGrid(int setGridSize)
{
    gridSize = setGridSize;
}
int Render::getSizeOfGrid()
{
    return gridSize;
}

void Render::setSizeOfCubes(int setCubeSize)
{
    cubeSize = setCubeSize;
}
int Render::getSizeOfCubes()
{
    return cubeSize;
}

void Render::setOffset(std::vector<int> setOffset)
{
    offset = setOffset;
}
std::vector<int> Render::getOffset()
{
    return offset;
}


void Render::display()
{
// Drawing code
}

编辑:

我现在已经按照您所说的方式更改了代码。现在我收到错误 LNK2005 和 LNK1169。现在出了什么问题?

编辑 2:(错误)

LNK2005

"class sf::RenderWindow Window" (?Window@@3VRenderWindow@sf@@A) 已在 Cubes.obj 中定义

C:\Users\George\Documents\C++\Projects\Don't fall\Don't fall\main.obj 1

.

LNK2005

"class std::basic_string,class std::allocator > status" (?status@@3V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@ @A) 已经在 Cubes.obj 中定义了

C:\Users\George\Documents\C++\Projects\Don't fall\Don't fall\main.obj 1

.

LNK1169

找到一个或多个多重定义的符号

C:\Users\George\Documents\C++\Projects\Don't fall\Debug\Don't fall.exe 1

Global.h:

#pragma once
#include <SFML\Graphics.hpp>

// This is where all my global variables will be


extern sf::RenderWindow Window(sf::VideoMode(500, 500), "Maximize window to play the game");
extern std::string status = "NULL";

【问题讨论】:

  • 您需要包含标题,省略类的重新定义,并正确地在方法前加上 Render:: (请参阅下面的答案)。
  • 您在 Render::Render() 的末尾缺少一个 }

标签: c++ visual-studio


【解决方案1】:

您的 Cubes.cpp 确实重新定义了 Render 类。通常,.h 文件具有类原型,而 .cpp 定义方法。

尝试将其添加到 Cubes.cpp 的顶部:

#include "Cubes.h"

从 Cubes.cpp 顶部删除它:

class Render
{
private:
    std::vector<float> rot;
    std::vector<int> boxCoords;
    std::vector<std::string> rlBoxCol;
    int gridSize;
    int cubeSize;
    std::vector<int> offset;

public:   

并从底部删除它:

};

【讨论】:

  • 感谢您的回复,但它并没有解决我的问题。但是,我按照您的建议和其他问题更新了代码。请查看新代码,以及我得到的错误。我还是找不到解决办法
【解决方案2】:

这不是您在 C++ 中提供类实现的方式。关键字class 定义了类,这是您在标题(.h 文件)中的内容。在.cpp 文件中,您希望实现您在头文件中定义的方法,因此您不应重新定义整个类。相反,您需要为类的方法(成员函数)提供实现,如下所示:

void Render::setRotation(std::vector<float> setRot)
{ // Set rotation
    rot = setRot;
}

std::vector<float> Render::getRotation()
{ // Get rotation
    return rot;
}

注意前缀Render::?这就是您如何表明您正在为类Render 的函数setRotation 提供实现。只需在你的cpp中添加这样的函数实现,不要将它们嵌套在class中,不要包含任何字段(成员字段已经在标题中定义,它们已经完成)。

更新

好的,所以根据更新的答案,您的链接器错误是指实例sf::RenderWindow Windowstd::string status;将main.obj(来自main.cpp?)与Cubes.obj 链接时会发生此错误。该错误告诉您main.objCubes.obj 都定义了这些变量。

我建议您阅读 C++ 中的“编译单元”以及符号的声明定义之间的区别;但要给出一个非常简短的总结:

本质上,编译器在单个“编译单元”上运行;您可以将其视为单个文件。 #include-statement 所做的基本上是将包含文件的内容复制/粘贴到编译单元中。因此,当您编译@​​987654337@ 时,它将遍历所有嵌套包含,直到它生成一个包含所有内容的巨大cpp 文件。然后它将把它构建到一个.obj 文件中。然后您对main.cpp 和您可能拥有的任何其他.cpp 文件执行相同的操作。最后,链接器将尝试将这些目标文件链接在一起以产生最终结果。

现在,如果链接器在链接两个对象时发现重复的定义,你会得到一个错误。所以你不能有两个同名的全局变量!如果Cubes.cppmain.cpp 都包含global.h,那么两个编译单元都包含全局变量定义Windowstatus。这会导致您的链接器错误。

这就是为什么您在标头中放置 声明(因为它包含在多个编译单元中),以及在源文件中放置 定义(通常不包含在其他地方)。您构建源文件以生成唯一包含定义的目标文件;所有其他目标文件仅引用声明。然后链接器可以将这些引用链接到在一个目标文件中找到的定义

所以你想声明标题中的变量,并将定义移到其他地方。例如,main.cpp;但这完全取决于您的应用程序的其余部分以及您要实现的目标。超出问题范围。

【讨论】:

  • 我刚刚尝试过,但我收到指向 main.obj 的错误。错误中的变量来自文件“Global.h”(和 Global.cpp),所以我认为我的全局变量搞砸了。
  • 那是不同的问题,您能用所需的详细信息编辑您的问题吗?
  • 来自类的变量与我的全局变量颜色相同。那么这是造成问题的原因吗?我需要一些构造函数来防止这种情况吗?
  • 最好发布实际错误以及这些全局文件中的内容。
  • 添加错误信息 :) 感谢您的帮助
猜你喜欢
  • 2014-11-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-23
  • 1970-01-01
相关资源
最近更新 更多