码迷,mamicode.com
首页 > 编程语言 > 详细

C++ 头文件重复包含解决之道

时间:2015-01-18 09:20:41      阅读:253      评论:0      收藏:0      [点我收藏+]

标签:c   c++   编译器   编程   

我们在C/C++编程中,经常出现这种类型的错误:error: redefinition of ‘struct student‘或者error: previous definition of ‘struct student‘。

字面来看,指的是重新定义或者先前已定义。下面我将针对这一类型问题给出一套系统的解决方案,看了以下文章后,相信以后对于这种问题将会胸有成竹,对于程序的设计也更加合理。

开门见山,我讲给出一个具体的例子。

1、实例

struct.h
struct student
{
    char name[20];
    int age;
};

club.h
#include "student.h"
#include <vector>
struct club
{
    char name[20];
    std::vector<student> members;
};

main.cpp
#include <iostream>
#include <cstring>
#include "student.h"
#include "club.h"
using namespace std;
int main()
{
    club club1;
    student stu1{"jin", 20};
    student stu2{"shia", 19};
    strcpy(club1.name, "gamelover");
    club1.members.push_back(stu1);
    club1.members.push_back(stu2);
    for(auto stu:club1.members)
    {
        cout<<stu.name<<endl;
    }
}

这个程序将输出以上错误。首先我们明白c++头文件在编译器中相当于插入包含的文件。因此对于最终的main.cpp,包含了两次student.h,解决这个问题方法有以下几种。

1.1利用ifndef来避免头文件重复包含

我们回忆下曾经学过的基础语法:#ifndef n和#define n。前者是若没有定义n,就执行下面的语句,后者是定义n。如果不记得请翻书或者谷歌。加上后的代码也给出来。
student.h
#ifndef STUDENT_H
#define STUDENT_H
struct student
{
    char name[20];
    int age;
};
#endif // STUDENT_H

club.h
#ifndef CLUB_H
#define CLUB_H
#include "student.h"
#include <vector>
struct club
{
    char name[20];
    std::vector<student> members;
};
#endif // CLUB_H

main.cpp
#include <iostream>
#include <cstring>
#include "student.h"
#include "club.h"
using namespace std;
int main()
{
    club club1;
    student stu1{"jin", 20};
    student stu2{"shia", 19};
    strcpy(club1.name, "gamelover");
    club1.members.push_back(stu1);
    club1.members.push_back(stu2);
    for(auto stu:club1.members)
    {
        cout<<stu.name<<endl;
    }
}

对于一种方法,我们要尽量了解其本质,为什么加上这几条语句就有效果?其实是编译时,每个文件只能编译一次(另一种理解方式是在最终文件中不能有命名冲突),而每个头文件被编译后,会定义一个XXX_H变量来标识,避免重复编译的方法就是判断是否已经定义了XXX_H即可。既然这样简单的道理,编译器其实有更简单的解决方案。

1.2编译器命令

在C++语言层面并不支持这种方法,但是随着越来越多的编译器对这个方案的支持,其实已成为事实标准,那就是 #pragma once。
到这就完了吗?NO!有些情况这种方法也会失效,比如...

2、互相包含

对上面的student.h做出一点小小的修改
#pragma once
#include "club.h"
struct student
{
    char name[20];
    int age;
    club myclub;
};

发现了新的错误!这是因为互相引用,比如在student中找club文件,club又引用了student,又找syudent文件,这样循环直到栈溢出。在这种情况下,上面的两种方法都是无用的。这里我们要思考下:既然头文件只是简单的代码插入,那么我们只要在一个文件中简单的声明需要的对象即可。如:
#pragma once
class club;
struct student
{
    char name[20];
    int age;
    club myclub;
};
但是我们发现还是错误!!这次错误是:error: field ‘myclub‘ has incomplete type。其实是因为club这里还没有定义,并不知道其大小,myclub大小未知。我们稍作改变:
#pragma once
class club;
struct student
{
    char name[20];
    int age;
    club *myclub;
};
这样就可以了。

3、总结

c++是一门相对复杂的语言,它的语法复杂性,无所不包的特性,导致了无数的陷阱,掌握它需要较大的努力,作为刚入门的菜鸟,得继续努力。

C++ 头文件重复包含解决之道

标签:c   c++   编译器   编程   

原文地址:http://blog.csdn.net/jr19911118730/article/details/42816789

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!