今天再看二叉树的知识,看着看着就看到C/C++的头文件及头文件重复定义这一块去了。以前就看到过这个问题,但是自己一直没有用到这方面的东西,今天遇到就顺便总结一下,等以后忘了再回来看看。

  首先明确一点C/C++头文件是要来干什么的?(http://baike.baidu.com/link?url=lMbCZqCAsBJ_rhifA82koGGjoJmbZUy1tTPNPzertEc7nxNr71Xqfm63GEuqA8Ze

  头文件的作用有三:
          1、C\C++采用源文件单独编译为object文件,最后有链接器链接object文件成为可执行文件头文件解决了彼源文件中变量和函数在此源文件中引用。
          2、头文件中的函数接口和全局变量占位符的作用和参数类型与表达式匹配的合法行检测的作用,早期的C编译器不具有后者的功能。
          3、便于一二进制的形式发行类库,因此源码实现的细节。

  一般用到的第三条比较多一点,就是在*.h的头文件中定义类,而不具体实现类的细节。把类的细节实现放在*.cpp文件中来实现。这样实现定义和实现的细节分开,使程序的结构更加清晰明了。

  举个例子:

      /Animal.h

      class Animal
     {
        private:
             char Gender;
             int Age;
        public:
             Animal(char gen,int age);
             Animal();
             char GetGender();
             int GetAge();
      };

  具体实现在Animal.cpp文件中实现

//这里必须包含定义的头文件

#include "Animal.h"

Animal::Animal()
{
 Gender='M';
 Age=0;
}

Animal::Animal(char gen,int age)
{
 Gender=gen;
 Age=age;
}

char Animal::GetGender()
{
 return Gender;
}

int Animal::GetAge()
{
 return Age;
}

这样类体的定义和实现就分开了。只需要在另一个cpp文件中定义一个主函数就可以直接用自己定义好说的类了,注意不要忘记包含头文件。

举个例子:

#include <iostream>
#include "Animal.h"
using namespace std;

int main()
{
 Animal a('F',14),s;
 cout<<a.GetAge()<<endl;
 cout<<a.GetGender()<<endl;

return 0;
}

这里涉及一个类,下面再来定义一个Bird类来讲讲头文件重复定义的问题:

同样先定义头文件:Bird.h

#include "Animal.h"
class Bird
{
private:
 Animal Property;
 bool Fly;
public:
 Bird();
 Bird(bool fly,Animal an);
 void SetFly();
 void SetNoFly();
 bool GetFly();
 Animal GetAnimalProperty();
};

注意这是由于该头文件中包含了#include "Animal.h"头文件,当再次在其他cpp文件中包含Bird.h和#include "Animal.h"时就会出现头文件重复定义。

编译时具体的错误信息:

Compiling...
RepeatHeadFile.cpp
e:\acm\acm 程序设计实战\repeatheadfile\animal.h(4) : error C2011: 'Animal' : 'class' type redefinition
Animal.cpp
Bird.cpp
执行 cl.exe 时出错.

Bird.cpp实现

#include "Bird.h"
Bird::Bird()
{
 Property=Animal();
 Fly=true;
}
Bird::Bird(bool fly,Animal an)
{
 Fly=fly;
 Property=an;
}

void Bird::SetFly()
{
 Fly=true;
}

void Bird::SetNoFly()
{
 Fly=false;
}

bool Bird::GetFly()
{
 return Fly;
}

Animal Bird::GetAnimalProperty()
{
 return Property;
}

解决办法是c/c++给出的预编译命令

#ifndef

#define

//头文件定义

...........

#endif

重新贴一下有预编译命令的头文件定义代码:Animal.h

#ifndef ANIMAL_H_H
#define ANIMAL_H_H
class Animal
{
private:
 char Gender;
 int Age;
public:
 Animal(char gen,int age);
 Animal();
 char GetGender();
 int GetAge();
};
#endif

Bird.h

#include "Animal.h"
#ifndef BIRD_H_H
#define BIRD_H_H
class Bird
{
private:
 Animal Property;
 bool Fly;
public:
 Bird();
 Bird(bool fly,Animal an);
 void SetFly();
 void SetNoFly();
 bool GetFly();
 Animal GetAnimalProperty();
};
#endif

小结:这些小问题当自己没遇到的绝得都是小问题没什么,但是当真正用的时候发现这也错那也错。很是郁闷,因此每每遇到这种小问题时不如做个笔记,放在网上最好不但自己方便查阅。也方便刚学的人参考,利人利己,何乐而不为!

自定义C/C++头文件以及头文件重复定义解决的更多相关文章

  1. keil C51中建立多文件时,变量重复定义的解决

    c/c++语言中有很多地方要用到extern,但是如果没有真正的了解它的意义,会给编程带来很大的麻烦,为了使大家少走弯路,特祥细的说明一下. 对于比较小的程序,一般只有一个c文件和一个头文件,全局变量 ...

  2. larave5.6 引入自定义函数库时,报错不能重复定义

    方法一:使用function_exists判断 方法二:使用命名空间 namespace test; function test(){ echo 'test/test'; } namespace te ...

  3. C++中的头文件(.h)和源文件(.cpp)都应该写什么?

    头文件(.h):写定义和声明写类的声明(包括类里面的成员和方法的声明).函数原型.#define常数等,但是一般来说不写具体的实现.注意: 1.在写头文件的时候需要注意,在开头和结尾处必须按照如下样式 ...

  4. C++的头文件和实现文件分别写什么

    在C++编程过程中,随着项目的越来越大,代码也会越来越多,并且难以管理和分析.于是,在C++中就要分出了头(.h)文件和实现(.cpp)文件,并且也有了Package的概念. 对于以C起步,C#作为& ...

  5. windows下使用gcc完成头文件和目标文件编译

    环境要求 安装了gcc win+r然后输入cmd , dos界面输入 gcc -v 查看有没有安装gcc 进入正题 新建 text.c文件键入如下代码: #include <stdio.h> ...

  6. Objective-C声明在头文件和实现文件中的区别

    Objective-C声明在头文件和实现文件中的区别 转自codecloud(有整理) 调试程序的时候,突然想到这个问题,百度一下发现有不少这方面的问答,粗略总结一下: 属性写在.h文件中和在.m文件 ...

  7. C中头文件在cpp文件中引用和.h文件引用

    1.编译器会单独编译每个cpp文件.头文件会复制到cpp文件中. 2.有时会遇到这样的一个问题a.cpp要调用b.cpp中的函数,而b.cpp又要调用a.cpp中的函数.这就牵扯到相互调用.这时如果我 ...

  8. C++ 中的模板类声明头文件和实现文件分离后,如何能实现正常编译?

    C++ 中的模板类声明头文件和实现文件分离后,如何能实现正常编译? 这个feature叫做Export Template,即外名模板,它的作用在于使得模板代码可依照C/C++语言习惯,将模板声明和实现 ...

  9. .h头文件和.c文件的作用和区别

    .h头文件和.c文件的作用和区别 在小工程中,.h的作用没有得到充分的使用,在大工程中才能充分体现出.h文件的作用. .h和.c文件都是代码.头文件好处有: 一:头文件便于共享,只需要添加一句“inc ...

随机推荐

  1. 基本概率分布Basic Concept of Probability Distributions 3: Geometric Distribution

    PDF version PMF Suppose that independent trials, each having a probability $p$, $0 < p < 1$, o ...

  2. C#调用c++Dll 结构体数组指针的问题

    参考文章http://blog.csdn.net/jadeflute/article/details/5684687 但是这里面第一个方案我没有测试成功,第二个方案我感觉有点复杂. 然后自己写啦一个: ...

  3. 【Beta】第二次任务发布

    后端 了解社区新建文章.添加评论(回复)的机制.整理成API文档,包括如何请求新建文章.新建评论(回复).如何获取文章内容和评论内容. 验收条件:文档PM要能看懂. 前端 微调数据输入部分的布局和操作 ...

  4. 【Alpha阶段】第四次Scrum例会

    会议信息 时间:2016.10.20 21:00 时长:20min 地点:大运村1号公寓5楼楼道 类型:日常Scrum会议 个人任务报告 姓名 今日已完成Issue 明日计划Issue 今日已做事务 ...

  5. mysql 生成排名字段

    假设有test表,下图为表机构和数据,score表示积分.现在要查询积分排名为第几的id?? 查询语句 select id,score,(@rowno:=@rowno+1) as rowno from ...

  6. Python基本数据类型之dict

    一.创建字典: d = { "name": "morra", #字典是无序的 "age": 99, "gender": ...

  7. 常见linux命令释义(第六天)——shell环境变量

    太懒了,这几天好像得了懒癌,一点都不想写博客.后来想想,知识嘛,还是分享出来的好.第一治自己的懒癌:第二顺便巩固下自己的知识. Linux的变量分为两种,一种是系统变量,是系统一经启动,就写进内存中的 ...

  8. POJ2239 Selecting Courses(二分图最大匹配)

    题目链接 N节课,每节课在一个星期中的某一节,求最多能选几节课 好吧,想了半天没想出来,最后看了题解是二分图最大匹配,好弱 建图: 每节课 与 时间有一条边 #include <iostream ...

  9. JAVASE 面试总结(1)

    1.什么是Java虚拟机?为什么Java被称作是"平台无关的编程语言"?Java虚拟机是一个可以执行Java字节码的虚拟机进程.Java源文件被编译成能被Java虚拟机执行的字节码 ...

  10. Navicat 的使用(一)

    1.创建连接 主机名 : 可以不写名称随意 主机名/IP地址:localhost或者127.0.0.1 都是本机的意思 端口:默认3306   尽量不要改怕与其余端口重复,如有重名端口系统会报错 用户 ...