【问题标题】:C++ include and redefinition of class errorC ++包含和重新定义类错误
【发布时间】:2015-11-29 09:23:25
【问题描述】:

我目前正在编写一个根据不同搜索歌曲的程序 参数。 在我的系统中有两种类型的歌曲:抒情和乐器。 因为我需要把它们都放在一个向量中,所以我有一个歌曲类和 一个 LyricsSong 和 InstrumentalSong 子类。

所以我有一个 Song.h 文件:

#include <stdio.h>
#include <iostream>
#include <string>


class Song
{
public:
    std::string title;
    virtual void print();
    virtual void printSong(std::string query);
};

还有乐器和歌词子类,它们是这样定义的:

class LyricsSong : public Song
class InstrumentalSong : public Song

都包含 Song.h,并且在它们中都定义了类 仅在头文件中。

当我尝试运行另一个使用这两个子类的文件时, 并包括:

#include "LyricsSong.h"
#include "InstrumentalSong.h"

(显然还有更多 cpp 库),我得到以下编译错误:

In file included from /cygdrive/c/Users/Username/Documents/C++ Workshop/ex2/ex2_code/InstrumentalSong.h:16:0,
                 from /cygdrive/c/Users/Username/Documents/C++ Workshop/ex2/ex2_code/songsParser.cpp:26:
/cygdrive/c/Users/Username/Documents/C++ Workshop/ex2/ex2_code/Song.h:6:7: error: redefinition of 'class Song'
 class Song
       ^
In file included from /cygdrive/c/Users/Username/Documents/C++ Workshop/ex2/ex2_code/LyricsSong.h:15:0,
                 from /cygdrive/c/Users/Username/Documents/C++ Workshop/ex2/ex2_code/songsParser.cpp:25:
/cygdrive/c/Users/Username/Documents/C++ Workshop/ex2/ex2_code/Song.h:6:7: error: previous definition of 'class Song'
 class Song
       ^

何时:

  • InstrumentalSong.h:16:0 和 LyricsSong.h:15:0 行是 i 包括“Song.h”
  • 行songsParser.cpp:25 和songsParser.cpp:26 是我的位置 包括 InstrumentalSong.h 和 LyricsSong.h
  • line Song.h:6:7: 是 Song.h 的定义(据说是 歌曲类,如上所示)。

我该怎么办? 附言我从不导入任何 cpp 文件,只导入头文件。

【问题讨论】:

  • 你缺少包括警卫:stackoverflow.com/questions/1653958/…
  • 我的问题是定义太多,没有漏掉,而且我不知道在这种情况下如何使用它们。
  • 我说的不是缺少定义,而是缺少包含守卫。你读过链接吗?

标签: c++ inheritance include polymorphism multiple-inheritance


【解决方案1】:

你必须告诉预处理器只包含你的头文件一次。您可以通过在所有*.h 文件的顶部添加#pragma once 来实现:

#pragma once

//Your header file's code

始终以这一行开头的头文件也是一个好习惯。

【讨论】:

  • #pragma once 不是标准的,在某些情况下无法使用。由于那些(不可移植的)问题,它显然没有标准化。 See here 解决一些问题。
  • 但它实际上解决了我的问题。我花了大约一个小时寻找解决方案,这^解决了它。但是为什么它有这个缺点呢?
【解决方案2】:

它们都包含“Song.h”文件,预处理器会两次获取文件内容。 您需要在 #ifndef #define 和 #endif 指令中写入“LyricsSong.h”和“InstrumentalSong.h”文件内容。像这样

#ifndef LYRICS_SONG_H
#define LYRICS_SONG_H

your code goes here.
...

#endif 

【讨论】:

  • 在大多数编译器中,您也可以使用更高效的#pragma 一次
  • @DawidPi 我不喜欢使用非标准的工具/功能,也不建议任何人这样做。
  • 最重要的是,他需要在Song.h 中添加一个包含保护。将其放入 LyricsSong.hInstrumentalSong.h 是很好的做法,但还不够。
  • 事实上,我理解这一点,我也更喜欢标准解决方案,但每个现代编译器都可以使用#pragma once。 msvs、gcc、clang 或其他。如果你有很多文件,它可以显着减少编译时间
  • 至少对于 gcc #pragma once 可能并不比标准包含守卫更有效,请参阅here。其他编译器可能也有类似的优化。
【解决方案3】:

正如已经回答的那样,我也会使用 #pragma 一次,它更方便、更干净。但请注意,它不是 C++ 标准,因此如果您必须使用不同的编译器(尽管它是一个广泛使用的扩展),则可能会出现问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-27
    • 2020-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多