今天再看二叉树的知识,看着看着就看到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. Newton-Raphson算法简介及其R实现

    本文简要介绍了Newton-Raphson方法及其R语言实现并给出几道练习题供参考使用. 下载PDF格式文档(Academia.edu) Newton-Raphson Method Let $f(x) ...

  2. 对JavaScript优化及规范的一些感想

    变量...... 1.一个变量只存一种类型的数据,2.尽量减少对隐式转换的依赖,这样可增强程序的可读性,日后修改程序时不至于混乱,3.使用匈牙利命名法,4.使用局部变量时记得加 var 进行声明,不然 ...

  3. 使用canvas绘制时钟

    使用canvas绘制时钟  什么使canvas呢?HTML5 <canvas> 元素用于图形的绘制,通过脚本 (通常是JavaScript)来完成.<canvas> 标签只是图 ...

  4. oneM2M标准发展神速 实现万物联网的愿景

    http://m2m.iot-online.com/news/2013102224849.html oneM2M则将负责解决独立于接取网路中通用的M2M服务层的关键需求:使其可更方便地嵌入于各种软硬体 ...

  5. Bitmap四种属性

    http://blog.csdn.net/rabbit_in_android/article/details/49967461 Bitmap: (1)     public Bitmap (int w ...

  6. css007 margin padding border

    css007 margin padding border 1.理解盒模型(盒模型:就是把一些东西,包括html各种标签都包含在一个 看不见的盒子里) 1/在web浏览器中任何标签都是一个盒子,内容的周 ...

  7. c# 操作datatable

    1.创建 datatable DataTable dt=new Datable();// 可以给表创建一个名字,tb 2.给表加个列名: dt.Columns.Add("id", ...

  8. 查询centos查看系统内核版本,系统版本,32位还是64位

    [root@centos01 ~]# lsb_release -a           #查看centos 版本为6.4LSB Version: :base-4.0-amd64:base-4.0-no ...

  9. DOCKER windows安装

    DOCKER windows安装 1.下载程序包 2. 设置环境变量 3. 启动DOCKERT 4. 分析start.sh 5. 利用SSH工具管理 6. 下载镜像 6.1 下载地址 6.2 用FTP ...

  10. Cloudservie将LocalStroage中的内容通过WAD自动上传到BLOB中

    开发云服务程序,如果使用Local stroage存储我们临时生成的日志或者文件并将它们自动上传到BLOB中,可以通过WAD来实现,具体如下: 1.配置webrole,开启Local stroage功 ...