今天再看二叉树的知识,看着看着就看到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. FZU 2191 完美的数字

    题目链接: 传送门 完美的数字 Time Limit: 1000MS     Memory Limit: 65536K 题目描述 Bob是个很喜欢数字的孩子,现在他正在研究一个与数字相关的题目,我们知 ...

  2. 利用php制作简单的文本式留言板

    del.php 代码如下: <html><head ><meta charset="utf-8"><title>我的留言板</ ...

  3. JSP+Servlet+JavaBean统计页面在线访问次数

    统计页面浏览次数:使用的是servlet实现统计次数传递给JSP页面 说明:我做的都比较接地气,意思就是比较简单! 效果图如下: 上代码 counter.java(它真的好简单,啥事不干,只是定义一个 ...

  4. 用面对对象方式定tab标签

    一些公共的底层的JS方法 var GLOBAL = {}; GLOBAL.namespace = function (str) { var arr = str.split('.'), o = GLOB ...

  5. 2-SAT 问题

    2-SAT 问题是k-SAT问题在k==2时的特殊情况,因为已经证明k>=3时的k-sat问题属于npc问题.所以在这里仅研究2-SAT的特殊情况.   何为2-sat问题? 简单地说就是有N个 ...

  6. JS-DOM2级封装练习题--点击登录弹出登录对话框

    <!doctype html><html lang="en"> <head> <meta charset="UTF-8" ...

  7. C#获取C++中修改过的float数组(指针),dll

    C++中 struct rankPoint{ float sim; }; ]){ ; i < ; i++) prank[i].sim = ; ; i < ; i++) prank[i].s ...

  8. lua 闭包

    --匿名函数使用upvalue i保存他的计数, 闭包是一个函数加上它可以正确访问的upvalues function newCounter() return function() i = i + r ...

  9. Java——按钮组件:JButton

    import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.Point; impor ...

  10. PyCharm 教程(四)显示行号

    PyCharm 教程(四)显示行号 在PyCharm 里,显示行号有两种办法: 1,临时设置.右键单击行号处,选择 Show Line Numbers. 但是这种方法,只对一个文件有效,并且,重启Py ...