循环包含,如何在不改变类层次结构的情况下解决这个问题。

3
            Animal
               |
           Mammal
               / \
      TwoLegged - FourLegged
         /           \
        Human      Lion

我有一个类层次结构,每个类都在自己的头文件中定义。现在当我在同一个位置包含Human.h和Lion.h时,我会得到一个Mammal重新定义的错误。
 error C2011: 'Mammal' : 'class' type redefinition

这是因为Mammal.h头文件同时被TwoLegged和OneLegged类调用。

然而,我不确定如何解决头文件中的循环依赖关系,因为我不能改变类层次结构。

有人能帮忙吗?

编辑:

Mammal头文件

#ifndef MAMMAL_H
#define MAMNAL_H

#include "stdafx.h"
#include "Animal.h"

class Mammal : public Animal
{
public:
    Mammal::Mammal();
    virtual Mammal::~Mammal();

    std::string mammal_name();
    int mammal_age();
    int mammal_expectedlifedays();
    bool mammal_hunter();
    int mammal_power();
    int mammal_birthrate();
    bool mammal_alive();

protected:
    Mammal::Mammal(const std::string& mname, int mexpectedlifedays, int mage, bool mhunter, int mpower, int mbirthrate, bool malive) : Animal(mname, mexpectedlifedays, mage,mhunter,  mpower, mbirthrate, malive)
    {}
private:
};

#endif

编译器给出的错误:
error C2011: 'Mammal' : 'class' type redefinition
see declaration of 'Mammal'

error C2504: 'Mammal' : base class undefined
error C2614: 'TwoLegged' : illegal member initialization: 'Mammal' is not a base or member

注意:这不是作业,否则我会标记它的。
提示:该段文本已经是中文,无需翻译。

4
你的头文件中有编译保护吗?#ifndef /#define/ #endif - John
3
你是否在使用预编译指令中的 include guards(包含保护)? - Jeff Linahan
@John:是的,我有那些编译保护。 - Tony The Lion
1
@Tony:你的Mammal.h中的包含保护可能有问题,或者你实际上在某个地方重新定义了class Mammal!从你描述的问题来看,没有循环包含(例如,如果Mammal.h包含Lion.h,就会是这种情况)。 - Ferdinand Beyer
1
@Tony:只要你有包含保护(这正是它们的作用),这就不是问题。而且这与循环无关,因为“哺乳动物”独立于“狮子”和“人类”。 - Ferdinand Beyer
显示剩余5条评论
4个回答

4
#pragma once

请在所有头文件的顶部添加此内容。但请记住,尽管编译器对其支持非常好,但它并不是标准。

最好使用#ifndef / #def / #endif! - Nico
1
支持不太好。众所周知,GCC没有它。 - rodrigo
当然,你肯定要根据你使用的编译器进行检查。但是,如果你的编译器支持它,那么它比包含保护更加清晰和不容易出错。 - K Mehta
@rodrigo 自从gcc 3.4版本开始就已经支持了。请参考http://gcc.gnu.org/gcc-3.4/changes.html - K Mehta
各位,这个讨论已经偏离主题了。很可能原帖作者忘记或者打错了包含保护宏(无论是哪种),而这个回答只能部分地提供帮助。 - Ferdinand Beyer

3

您需要使用包含防护(include guards)。典型的形式如下:

#ifndef NAME_OF_HEADER_H
#define NAME_OF_HEADER_H

// Rest of header code here.

#endif

由于在C ++中的#include只是将当前文件中的文本复制粘贴,如果同一个头文件被包含两次,则该文本将导致重复的类定义。而include guard的作用是防止多次包含同一头文件。
编辑:问题在于您检查了MAMMAL_H的定义,然后定义了MAMNAL_H(请注意定义版本中的N)。出于这个原因,我总是复制粘贴以生成我的include guards。

@Tony The Tiger:你确定了吗?还是可以重新检查一下,确保所有文件都正确放置了! - Alok Save
@Tony The Tiger 在这种情况下,我认为我们需要看到一个最小的例子来展示你遇到的问题。 - Mark B

0

我猜你忘记加入保护宏了。像John建议的那样使用#ifndef /#ifdef/ #endif。


-1 - Alnitak
这很公平!我没有那个意思。对不起,伙计们。 - Nico

0
#ifndef MAMMAL_H
#define MAMMAL_H



... definition of mammal


#endif

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接