帮我看看这个头文件该怎么写? 看着简单却不好实现呢

donaroo 2008-07-06 12:57:29
目的:
   在头文件中定义函数和全局变量(同时赋初值),并且如果已经定义过了就不再定义,而只是声明。


我下面的做法不能成功:

#ifndef MYTEST_H
#define MYTEST_H
extern "C" int g_i = 1;
extern "C" int JustTest(){
return g_i;
}
#else
extern "C" int JustTest();
#endif


在被两个cpp文件引用过这个头文件后会提示重复定义。  
我知道把定义部分放在cpp文件中,头文件只放声明可以解决这个问题。   能不能只通过一个头文件来解决?

各位高手出招
...全文
1173 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
donaroo 2008-07-19
  • 打赏
  • 举报
回复
后来也想了想,问题是在这里,引起内存分配的东西不该放在头文件里

mymtom 2008-07-09
  • 打赏
  • 举报
回复
[Quote=引用楼主 donaroo 的帖子:]
目的:
在头文件中定义函数和全局变量(同时赋初值),并且如果已经定义过了就不再定义,而只是声明。


我下面的做法不能成功:
C/C++ code#ifndef MYTEST_H#defineMYTEST_Hextern"C"intg_i=1;extern"C"intJustTest(){returng_i;
}#elseextern"C"intJustTest();#endif

在被两个cpp文件引用过这个头文件后会提示重复定义。
我知道把定义部分放在cpp文件中,头文件只放声明可以解决这个问题。   能不能只通过一…
[/Quote]
仔细看过才发现楼主的想法有问题。
头文件不是定义函数和全局变量的正确地方。
头文件的作用是声明函数和全局变量,以及定义宏和数据结构。
函数和全局变量定义应该在.c文件里。

简单的说:
.h文件不应该引起内存分配。
引起内存分配的语句都应该放在.c里。
mymtom 2008-07-09
  • 打赏
  • 举报
回复
其实,变量的声明需要用extern, 函数的声明可以不用extern的。
比如getopt.h

/* $NetBSD: getopt.h,v 1.4 2000/07/07 10:43:54 ad Exp $ */
/* $FreeBSD: src/include/getopt.h,v 1.6 2004/02/24 08:09:20 ache Exp $ */

/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Dieter Baron and Thomas Klausner.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

#ifndef _GETOPT_H_
#define _GETOPT_H_

#include <sys/cdefs.h>

/*
* GNU-like getopt_long()/getopt_long_only() with 4.4BSD optreset extension.
* getopt() is declared here too for GNU programs.
*/
#define no_argument 0
#define required_argument 1
#define optional_argument 2

struct option {
/* name of long option */
const char *name;
/*
* one of no_argument, required_argument, and optional_argument:
* whether option takes an argument
*/
int has_arg;
/* if not NULL, set *flag to val when option found */
int *flag;
/* if flag not NULL, value to set *flag to; else return value */
int val;
};

__BEGIN_DECLS
int getopt_long(int, char * const *, const char *,
const struct option *, int *);
int getopt_long_only(int, char * const *, const char *,
const struct option *, int *);
#ifndef _GETOPT_DECLARED
#define _GETOPT_DECLARED
int getopt(int, char * const [], const char *);

extern char *optarg; /* getopt(3) external variables */
extern int optind, opterr, optopt;
#endif
#ifndef _OPTRESET_DECLARED
#define _OPTRESET_DECLARED
extern int optreset; /* getopt(3) external variable */
#endif
__END_DECLS

#endif /* !_GETOPT_H_ */
mymtom 2008-07-09
  • 打赏
  • 举报
回复
楼主的想法很好,可以参考一些现成的库的写法,俺比较推荐这种写法。

/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Berkeley Software Design, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)cdefs.h 8.8 (Berkeley) 1/9/95
* $FreeBSD: src/sys/sys/cdefs.h,v 1.88.2.2 2006/01/31 17:57:16 stefanf Exp $
*/

#ifndef _SYS_CDEFS_H_
#define _SYS_CDEFS_H_

#if defined(__cplusplus)
#define __BEGIN_DECLS extern "C" {
#define __END_DECLS }
#else
#define __BEGIN_DECLS
#define __END_DECLS
#endif

/* ... */

#endif /* !_SYS_CDEFS_H_ */



/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
* ...
* ...
*
* @(#)stdio.h 8.5 (Berkeley) 4/29/95
* $FreeBSD: src/include/stdio.h,v 1.56.8.1 2006/01/31 17:57:17 stefanf Exp $
*/

#ifndef _STDIO_H_
#define _STDIO_H_

#include <sys/cdefs.h>
#include <sys/_null.h>
#include <sys/_types.h>

/* ... */

#define stdin __stdinp
#define stdout __stdoutp
#define stderr __stderrp

__BEGIN_DECLS
/*
* Functions defined in ANSI C standard.
*/
void clearerr(FILE *);
int fclose(FILE *);
int feof(FILE *);
int ferror(FILE *);
int fflush(FILE *);
int fgetc(FILE *);

/* ... */
__END_DECLS
#endif /* !_STDIO_H_ */

tesling 2008-07-09
  • 打赏
  • 举报
回复
楼主,就算找到了一种好的方法又有什么意义呢

头文件声明,实现文件定义,反过来能有什么好处呢

如果在只有几个文件的工程中,所有定义和声明都放在一个cpp文件中也可以搞定,但是这样根本没有意义
xkyx_cn 2008-07-09
  • 打赏
  • 举报
回复
单独放在一个cpp中,在h中声明,不挺好的吗?难道这样很难实现?
晨星 2008-07-09
  • 打赏
  • 举报
回复
不能,头文件天生是用来被人包含的,所以两个以上的cpp文件包含同一个头文件是很平常的事情。
因此,头文件中应该只放一些声明性的东西。
当然,也可以有类定义、模板、内联函数定义等等。说白了,就是只要编译器允许在多个编译单元(一个cpp以及它所直接或间接包含的头文件)中多次出现的,都适合放头文件,否则,就只能放cpp源文件。
donaroo 2008-07-08
  • 打赏
  • 举报
回复
谢谢前边的回复~~ 可是就不能只用一个头文件实现么 其他地方用这些函数或变量的时候 仅引用一个头文件就可以
K行天下 2008-07-06
  • 打赏
  • 举报
回复
[Quote=引用楼主 donaroo 的帖子:]
目的:
   在头文件中定义函数和全局变量(同时赋初值),并且如果已经定义过了就不再定义,而只是声明。


我下面的做法不能成功:

C/C++ code
#ifndef MYTEST_H
#define MYTEST_H
extern "C" int g_i = 1;
extern "C" int JustTest(){
return g_i;
}
#else
extern "C" int JustTest();
#endif



在被两个cpp文件引用过这个头文件后会提示重复定义。  
我知道把定义部分放在cpp文件中,头…
[/Quote]
不管怎样 不建议将变量定义放到头文件!
费力不讨好
shi8430419 2008-07-06
  • 打赏
  • 举报
回复
头文件中只要申明就够了,具体的定义放到CPP中去
非完美主义者 2008-07-06
  • 打赏
  • 举报
回复
2楼的方法好。
在头文件找那个将函数声明也extern吧
artman 2008-07-06
  • 打赏
  • 举报
回复
头文件
#ifndef _MYTEST_H_
#define _MYTEST_H_
extern int g_i; //变量声明
int JustTest(); //函数声明

#endif //#ifndef _MYTEST_H_



在任意.CPP或新建一个cpp中实现它们
#include "mytest.h"

int g_i=1; //实现
int JustTest() //实现
{
return g_i;
}

其他CPP 可任意#include 该头文件。

楼上的做法,似乎越搞越乱!

du51 2008-07-06
  • 打赏
  • 举报
回复
在当前CPP文件最顶部...定义
#ifndef XXX_CPP_
#define XXX_CPP_
#endif



在头文件里
#ifdef XXX_CPP_
void print_hello()
{
printf("Hello\n");
}
#else
void print_hello();
#endif


另建议EXTERN "C"不要一个一个的来...直接全括起来..看起来清晰点.

69,382

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧