今天再看二叉树的知识,看着看着就看到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. 常见linux命令释义(第二天)

    查看磁盘与目录的容量. df 与du df  是英语Disk Free的意思.磁盘空余. df -h  -h中h指的是一human(人类)的角度,即用GB,MB的格式显示.这个比较常用,还有其他的选项 ...

  2. HTML 速查列表

    HTML 基本文档 <!DOCTYPE html> <html> <head> <title>文档标题</title> </head& ...

  3. 快捷键&小技巧&备忘录

    shift+鼠标滚轮:实现左右移动 alt+鼠标左键双击:打开属性 chrome中在F12下的Element中,可以先选中某一项,可以直接按住F2进行编辑 chrome中element的右下方我们可以 ...

  4. 签名有元程序集 Signed Friend Assemblies

    下面的例子演示了创建签名程序集和有元程序集.这就要求两个程序集都是强命名,在下面的例子中,两个程序集都用了同一个秘钥,也可以用不同的秘钥. 1. 生成秘钥, 这个在前面的博客中有说明,生成秘钥文件sn ...

  5. jquery的$.extend()、$.fn和$.fn.extend()

    一种是类级别的插件开发,即给jquery添加新的全局函数,相当于给jquery类本身添加方法.如$.ajax()等,这就是用$.extend()实现 jquery的全局函数就是属于jquery命名空间 ...

  6. 细说Linux下软件包的安装与管理

    一 源码安装方式      由于linux操作系统开放源代码,因而在其上安装的软件大部分也都是开源软件,例如apache.tomcat.php等软件.开源软件基本都提供源码下载,源码安装的方式:源码安 ...

  7. WSAStartup

    WSAStartup,是Windows Sockets Asynchronous的启动命令.Windows下的网络编程接口软件 Winsock1 或 Winsock2 里面的一个命令. 外文名 WSA ...

  8. CSS 中背景图片定位方法

    三种: 关键字:background-position: top left; 像素:background-position: 0px 0px; 百分比:background-position: 0% ...

  9. asp.net+mysq 数据库操作类

    对数据库操作的使用方法: 1.引入命名空间 2.操作.三四行代码即可完成数据操作.类似于: using System; using System.Data; using System.Text; us ...

  10. Unity Sprite Atlas Compression

    http://forum.unity3d.com/threads/2d-sprite-packer-and-pvrtc.218633/ http://docs.unity3d.com/Manual/S ...