为什么在C++中,类可以定义在头文件而不冲突,而函数则会(除inline)

u011609612 2013-08-08 11:46:05
类的行为和函数为什么会有这么大的差别?


类可以定义在头文件,而函数则不行(除非是内联)

怎么解释类定义在头文件中的概念?

难道定义在头文件中后,不同的源文件引用的时候会产生不同的副本?然后这些副本就是文件作用域的?

跪请高手解释
...全文
1162 27 打赏 收藏 转发到动态 举报
写回复
用AI写文章
27 条回复
切换为时间正序
请发表友善的回复…
发表回复
lm_whales 2013-08-13
  • 打赏
  • 举报
回复
定义和声明 1) 定义就是声明,声明不一定就是定义,声明的意思是已经定义了。 定义是直接说已经定义了,非定义声明,是间接说已经定义了。 声明,不需要明白告诉你,定义成什么样子,你懂得就行。 定义,必须清晰,不能含糊,因为要分配空间。 2) C类型定义,等同于声明。因为没有定义数据,和代码。 3) C++类内定义的成员函数,友元函数,静态函数,可以看作inline 定义,地位相当于声明。 C++类内定义的成员变量,只是一种声明,不是真正的定义,只有用这个类定义对象,成员变量才真正有定义。 C++静态变量,通常要在类外定义,除非是静态整型常量,用常量表达式定义,才可以定义在类内部 。 C++ 类定义,实际上也是类型定义,等同于声明。 只是,类内部可以定义函数,与C类型定义有所不同。 4)常量定义可以看做声明。 5)C++ 把文件静态变量的定义看作声明,可以放到头文件里。 6)C++ 模板,实际上也可以看做声明。 因为模板在使用的时候才会实例化,生成一个可以使用的类型或者函数。 所以,头文件里面,要么是声明。 要么是可以看做声明的定义。 这些东西,都不会造成命名冲突,于是放在头文件里。
Scorpiour 2013-08-12
  • 打赏
  • 举报
回复
你确定是类函数定义而不是类函数声明?
lm_whales 2013-08-12
  • 打赏
  • 举报
回复
.h,.h,.cpp---> .cpp .Cpp -->.obj C++ 把头文件的所有内容汇总到.cpp 最后生成新的.cpp ---所有头文件都已经扩展的.cpp,在内存或者临时文件中--- 然后由此新的.cpp 生成 目标文件。 至于 预编译头文件,只是把经常使用的代码(通常是库代码),只进行一次扩展(预编译),其他引用预编译头文件的文件,直接汇入预编译的代码。 即整个工程的所有引用预编译头文件的代码,只编译一次,其他.CPP 都插入预编译的代码,以节省编译时间,只是编译器提供的一种技巧而已。
tcmakebest 2013-08-11
  • 打赏
  • 举报
回复
类的定义就是定义,三个人同时看到楼主,楼主还是同一个楼主
「已注销」 2013-08-10
  • 打赏
  • 举报
回复
引用 17 楼 u010828523 的回复:
一句话给你搞定,类的定义是内部连接,非内联函数是外部连接,内部连接是指该类只能在当前文件有效,所以可被多个文件包含。
那是不是内部连接相当于文件作用域? 能更深入的说说什么是内部连接吗
  • 打赏
  • 举报
回复
一句话给你搞定,类的定义是内部连接,非内联函数是外部连接,内部连接是指该类只能在当前文件有效,所以可被多个文件包含。
锋林 2013-08-10
  • 打赏
  • 举报
回复
引用 4 楼 yulinlang 的回复:
请参考《C++ Primer中文版》第四版 人民邮电出版社 P58: 因为头文件包含在多个源文件中,所以不应该含有变量或函数的定义。 对于头文件不应该含有定义这一规则,有三个例外。头文件可以定义类、值在编译时就已经知道的const对象和inline函数。这些实体可在多个源文件中定义,只要每个源文件中的定义是相同的。 在头文件中定义这些实体,是因为编译器需要它们的定义(不只是声明)来产生代码。
正解!
jiandingzhe 2013-08-10
  • 打赏
  • 举报
回复
引用 15 楼 lpcads 的回复:
[quote=引用 14 楼 jiandingzhe 的回复:] [quote=引用 3 楼 u011609612 的回复:] 那好,为什么结构就只是声明而已呢?怎么理解呢
因为只有机器码和静态数据(所占据的空间)是实现,是实际存在于可执行映像中的东西。结构只是描述了对数据的组织方式,所以是声明。 在编译生成的东西里,是没有结构(或者对象)这种东西的。有的只是依据结构所描述的组织方式,对数据进行的使用。 比如下面的C代码:

typedef struct
{
    int foo;
    int bar;
} MyStruct;

int main(int argc, char** argv)
{
    MyStruct data = {1,2};
    printf("foo: %d, bar: %d\n", data.foo, data.bar);
}
编译得到的东西,大致是这样的:

压栈int那么大的字节(argc)
压栈指针那么大的字节(argv)

压栈MyStruct那么大的字节(data)

将data的foo位置,int那么大的字节赋值为1
将data的bar位置,int那么大的字节赋值为2

压栈printf第一个参数的静态字符串所在的地址
将data的foo位置,int那么大的字节压栈
将data的bar位置,int那么大的字节压栈
调用printf函数
清栈

清栈,退出
你看这里面,哪里有struct这种东西了?[/quote] 顺序反了[/quote] 其实咱不会汇编,纯YY的,咩哈哈哈!
taoqilin 2013-08-10
  • 打赏
  • 举报
回复
类的定义是内部链接?那就不会推荐在头文件里定义类了。
「已注销」 2013-08-10
  • 打赏
  • 举报
回复
如果就这样,那也可以简单理解为以CPP文件为单元的意思了。
  • 打赏
  • 举报
回复
引用 18 楼 u011609612 的回复:
[quote=引用 17 楼 u010828523 的回复:] 一句话给你搞定,类的定义是内部连接,非内联函数是外部连接,内部连接是指该类只能在当前文件有效,所以可被多个文件包含。
那是不是内部连接相当于文件作用域? 能更深入的说说什么是内部连接吗[/quote] 内部连接已经给你说清楚了啊,就是类似于静态变量那样的,只能在它定义的文件里使用,也就是说只能内部使用它,你在main.cpp中包含了内部连接的函数,那么这个函数就相当于在main.cpp中定义的一样,只在main.cpp中有效,你在test.cpp中包含了内部连接的函数,那么这个函数就相当于在test.cpp中定义的一样,只在test.cpp中有效,多个.cpp文件都可以包含,而不会有任何的冲突,如果还不能理解,那么不建议再学了。
passion_wu128 2013-08-10
  • 打赏
  • 举报
回复
C++之父的大作 《the c++ programming language》有专门解释。
「已注销」 2013-08-09
  • 打赏
  • 举报
回复
那好,为什么结构就只是声明而已呢?怎么理解呢
max_min_ 2013-08-09
  • 打赏
  • 举报
回复
在c++中 类和结构体其实是差不多的! 都是为了封装封装内部类型而已!只不过类的用法更加灵活广泛,还引入多态继承这些 在头文件里,也只是申明而已,并没有产生实际的类对象!
ri_aje 2013-08-09
  • 打赏
  • 举报
回复
哪有这种说法?上点儿代码秀一下你到底什么意思。
lpcads 2013-08-09
  • 打赏
  • 举报
回复
引用 14 楼 jiandingzhe 的回复:
[quote=引用 3 楼 u011609612 的回复:] 那好,为什么结构就只是声明而已呢?怎么理解呢
因为只有机器码和静态数据(所占据的空间)是实现,是实际存在于可执行映像中的东西。结构只是描述了对数据的组织方式,所以是声明。 在编译生成的东西里,是没有结构(或者对象)这种东西的。有的只是依据结构所描述的组织方式,对数据进行的使用。 比如下面的C代码:

typedef struct
{
    int foo;
    int bar;
} MyStruct;

int main(int argc, char** argv)
{
    MyStruct data = {1,2};
    printf("foo: %d, bar: %d\n", data.foo, data.bar);
}
编译得到的东西,大致是这样的:

压栈int那么大的字节(argc)
压栈指针那么大的字节(argv)

压栈MyStruct那么大的字节(data)

将data的foo位置,int那么大的字节赋值为1
将data的bar位置,int那么大的字节赋值为2

压栈printf第一个参数的静态字符串所在的地址
将data的foo位置,int那么大的字节压栈
将data的bar位置,int那么大的字节压栈
调用printf函数
清栈

清栈,退出
你看这里面,哪里有struct这种东西了?[/quote] 顺序反了
jiandingzhe 2013-08-09
  • 打赏
  • 举报
回复
引用 3 楼 u011609612 的回复:
那好,为什么结构就只是声明而已呢?怎么理解呢
因为只有机器码和静态数据(所占据的空间)是实现,是实际存在于可执行映像中的东西。结构只是描述了对数据的组织方式,所以是声明。 在编译生成的东西里,是没有结构(或者对象)这种东西的。有的只是依据结构所描述的组织方式,对数据进行的使用。 比如下面的C代码:

typedef struct
{
    int foo;
    int bar;
} MyStruct;

int main(int argc, char** argv)
{
    MyStruct data = {1,2};
    printf("foo: %d, bar: %d\n", data.foo, data.bar);
}
编译得到的东西,大致是这样的:

压栈int那么大的字节(argc)
压栈指针那么大的字节(argv)

压栈MyStruct那么大的字节(data)

将data的foo位置,int那么大的字节赋值为1
将data的bar位置,int那么大的字节赋值为2

压栈printf第一个参数的静态字符串所在的地址
将data的foo位置,int那么大的字节压栈
将data的bar位置,int那么大的字节压栈
调用printf函数
清栈

清栈,退出
你看这里面,哪里有struct这种东西了?
小耸 2013-08-09
  • 打赏
  • 举报
回复
楼主应该要把类的定义当作一个新的数据结构的声明。就像typedef,struct xxx一样,是可以放在头文件中的。
vuqrzk5w 2013-08-09
  • 打赏
  • 举报
回复
引用 11 楼 vuqrzk5w 的回复:
因为C++ 不等于 C C++就规定允许在.h文件定义类
刚才还有个哥们问为什么可以"预编译头文件",编译本质就是解析,C++编译器在实现的时候解析一下.h文件不就行了.(链接才是生成可执行文件)
vuqrzk5w 2013-08-09
  • 打赏
  • 举报
回复
因为C++ 不等于 C C++就规定允许在.h文件定义类
加载更多回复(7)

64,635

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

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