【问题标题】:Why does compiler throw an redefinition error in classes? [duplicate]为什么编译器会在类中抛出重新定义错误? [复制]
【发布时间】:2020-07-09 21:27:16
【问题描述】:

我在重新定义时遇到问题,我尝试过 #pragma 一次和 #ifndf 语句,但这些都不适合我。 我的 main.cpp


#include <iostream>
#include "kolo.h"
#include "prostokat.h"
#include "trojkat.h"
using namespace std;
//overloading
void zmienno(float x)
{
    cout<<x;
}
void zmienno(int x)
{
    cout<<x;
}
int main()
{
    //tworzenie obiektu zmienna lokalna
    Kolo kolo(5);
    Trojkat trojkat(1,2,3);
    Prostokat prostokat(1,2);
    //wskaznik
    Kolo * wskkolo = new Kolo(5);
    Trojkat * wsktrojkat = new Trojkat(1,2,3);
    Prostokat * wskprostokat = new Prostokat(1,2);
    //konstruktory zaprezentowane wyżej, metody np:
    double pole = kolo.Pole(); //pole kola
    double obwod = wsktrojkat->Obwod(); //obwod trojkata
    kolo.SetR(3);
    pole = kolo.Pole(); // inne pole po zmiane R
    FiguraPlaska *wsk[3];
    wsk[0]=wskkolo;
    wsk[1]=wskprostokat;
    wsk[2]=wsktrojkat;
    for(int i=0;i<3;i++)
    {
        cout<<wsk[i]->Pole()<<endl;//metody wirtualne
    }
    wskprostokat->~Prostokat();
    wskkolo->~Kolo();
    wsktrojkat->~Trojkat();
    // overriding -> polimorfizm metody pole, obwod
    // overloading: funkcje w linii nr8
    zmienno(2);
    //ta sama nazwa funkcji, rozszerzona o inne typy argumentow
    delete[]wsk;
    delete wskkolo,wskprostokat,wsktrojkat;



    return 0;
}

我的头文件之一,因为每个文件中的结构都是相同的,包括 figuraplaska.h


#pragma once
#include "figuraplaska.h"

class Prostokat : public FiguraPlaska {
private:
 double a,b;
protected:
 void Wypisz(std::ostream& out) const override;
public:
 Prostokat(double a, double b);
 double GetA() const;
 void SetA(double a);
 double GetB() const;
 void SetB(double b);
 double Obwod() override;
 double Pole() override;

 ~Prostokat() override;
};

和 figuraplaska.h



#include <iostream>
using namespace std;

class FiguraPlaska {
protected:
 virtual void Wypisz(std::ostream& out) const = 0;
 friend std::ostream& operator<<(std::ostream& os, const FiguraPlaska& figura);
public:
 virtual double Pole() = 0;
 virtual double Obwod() = 0;
 virtual ~FiguraPlaska();
};

错误是


    [Running] cd "/home/bj/Pulpit/PO1/" && g++ main.cpp -o main && "/home/bj/Pulpit/PO1/"main
In file included from prostokat.h:2:0,
                 from main.cpp:3:
figuraplaska.h:5:7: error: redefinition of ‘class FiguraPlaska’
 class FiguraPlaska {
       ^~~~~~~~~~~~
In file included from kolo.h:2:0,
                 from main.cpp:2:
figuraplaska.h:5:7: note: previous definition of ‘class FiguraPlaska’
 class FiguraPlaska {
       ^~~~~~~~~~~~
In file included from trojkat.h:2:0,
                 from main.cpp:4:
figuraplaska.h:5:7: error: redefinition of ‘class FiguraPlaska’
 class FiguraPlaska {
       ^~~~~~~~~~~~
In file included from kolo.h:2:0,
                 from main.cpp:2:
figuraplaska.h:5:7: note: previous definition of ‘class FiguraPlaska’
 class FiguraPlaska {
       ^~~~~~~~~~~~
main.cpp: In function ‘int main()’:
main.cpp:45:13: warning: deleting array ‘wsk’
     delete[]wsk;
             ^~~

[Done] exited with code=1 in 2.043 seconds


我不知道如何修复它,有什么建议吗?互联网上没有任何帮助对我有用:/

【问题讨论】:

  • 您是否使用 #ifndef + #define 保护了头文件的内容?我的意思是只有#ifndef 是不够的
  • 如果不显示代码和错误消息,就无法提供帮助
  • 哦,我不知道为什么不添加整条消息
  • 请创建minimal reproducible example。您需要将代码减少到重现错误的最低限度。
  • @BartekJuśkiewicz 正如我所说你错过了使用#ifndef + #define 保护

标签: c++ class oop


【解决方案1】:

在 figuraplaska.h 的开头添加类似的内容

#ifndef FIGURAPLASKA_H_
#define FIGURAPLASKA_H_

最后加上

#endif

这样做您的文件内容将不会在每个源文件中包含两次

对其他头文件做类似的事情(当然使用不同的宏)


所以 figuraplaska.h 变成了例如

#ifndef FIGURAPLASKA_H_
#define FIGURAPLASKA_H_

#include <iostream>
using namespace std;

class FiguraPlaska {
protected:
 virtual void Wypisz(std::ostream& out) const = 0;
 friend std::ostream& operator<<(std::ostream& os, const FiguraPlaska& figura);
public:
 virtual double Pole() = 0;
 virtual double Obwod() = 0;
 virtual ~FiguraPlaska();
};

#endif

正如评论中所说,您的行中有问题

delete wskkolo, wskprostokat, wsktrojkat;

因为只有 wsktrojkat 被删除:逗号分隔的表达式的值是最后一个表达式的值

将这一行替换为

delete wskkolo;
delete wskprostokat;
delate wsktrojkat;

另一个问题是你之前有这些行:

wskprostokat->~Prostokat();
wskkolo->~Kolo();
wsktrojkat->~Trojkat();

删除它们,在执行 delete wskprostokat 时将应用 ~Prostokat

并且还删除该行

删除[]wsk;

因为wsk是放在栈中的,所以没有分配到堆中:

FiguraPlaska *wsk[3];

【讨论】:

  • 所以你的意思是 #endif 在整个代码的末尾或在定义头文件的末尾
  • @BartekJuśkiewicz 每个头文件的开头和结尾。或者你可以把#pragma once放在每个头文件的开头。
  • @BartekJuśkiewicz #endif 完成了 #ifndef 所以当然它在头文件的末尾
  • @john 我做到了,但对这个问题没有帮助
  • @BartekJuśkiewicz 这是一个非常不同的问题,您似乎没有定义 main 或者您没有编译/链接包含它的文件与其他文件。我回答了您最初的问题并在我的回答中提供了更多输入,请接受我的回答以标记您的初始问题已关闭(What should I do when someone answers my question?)然后如果需要打开一个新问题
猜你喜欢
  • 2023-03-30
  • 1970-01-01
  • 1970-01-01
  • 2023-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-14
  • 1970-01-01
相关资源
最近更新 更多