C++中的inline函数的实现部分应该放在哪里呢?

clever101
博客专家认证
2007-02-10 05:10:52
C++中的inline函数的实现部分到底该放在哪里呢?

C++中的类中inline函数的实现部分究竟放在哪里? 下面是两位专家的说法:
下面引自林锐博士的《高质量C++编程》P67


定义在类声明之中的成员函数将自动地成为内联函数,例如
class A
{
public:
void Foo(int x,int y);{ } // 自动地成为内联函数
}

将成员函数的定义体放在类声明之中虽然能带来书写上的方便,但不是一种良好的编程风格,上例应该改成:
// 头文件:
class A
{
public:
void Foo(int x, int y);
}

// 定义头文件
inline void A::Foo(int x, int y)
{

}


C++的发明者Bjarne Stroustrup博士在他所著的书《C++语言的设计和演化》中则是这样论述这个问题(见《C++语言的设计和演化》P12):
在带类的C中只有成员函数能做成在线(注:也就是设计为inline函数)的,而要求函数成为在线只有一种方式,那就是把它的放进类的声明之中。例如:
class stack
{
/* … /*
char pop()
{
If(top<=min) error(“stack underflow”);
return *--top;
}
};
事实上,那时也看到这会使类的声明显得比较杂乱。另一方面,这看起来也是个好东西,因为它不鼓励在线函数的过度使用。关键字inline和允许在线成员函数的功能都是后来由C++提供的。例如,在C++中可以写下面这样的代码:
class stack
{
/* … /*
char pop();
};

Inline char stack:: pop()
{
If(top<=min) error(“stack underflow”);
return *--top;
}

照两位专家的说法,inline函数的实现代码似乎既可以放在.h文件,也可以放在.cpp文件。实际上是不是这样呢?我使用VC6.0做了一个测试程序(Win32控制台程序):
程序运行环境:英文版Win Xp sp2
程序编译环境:VC++ 6.0
首先我把inline函数的实现代码可以放在.h文件
测试程序如下:
// MyString.h
#ifndef MY_STRING_H
#define MY_STRING_H

#include <string.h>

class CMyString
{
private:
char *pszData;
public:
CMyString();
CMyString(char *psz);
int GetLength()
{
return strlen(pszData);
}
~CMyString();
};

#endif
#endif

// MyString.cpp

#include "stdafx.h"
#include "MyString.h"
#include <iostream.h>

CMyString::CMyString()
{
pszData = new char[20];
}

CMyString::CMyString(char *psz)
{
pszData = new char[20];
strcpy(pszData,psz);
}

CMyString::~CMyString()
{
delete []pszData;
pszData = NULL;
}


// TestString.cpp

#include "stdafx.h"
#include "MyString.h"
#include <iostream.h>

int main(int argc, char* argv[])
{
CMyString str("Hello World!");
int strlen = str.GetLength();
cout<<strlen<<endl;
return 0;
}

程序编译运行成功。

现在我把inline函数的实现代码可以放在.cpp文件(主要修改了MyString.h和MyString.cpp)
// MyString.h
#ifndef MY_STRING_H
#define MY_STRING_H

#include <string.h>

class CMyString
{
private:
char *pszData;
public:
CMyString();
CMyString(char *psz);
int GetLength();
~CMyString();
};

#endif

// MyString.cpp

#include "stdafx.h"
#include "MyString.h"
#include <iostream.h>

CMyString::CMyString()
{
pszData = new char[20];
}

CMyString::CMyString(char *psz)
{
pszData = new char[20];
strcpy(pszData,psz);
}

inline int CMyString::GetLength()
{
return strlen(pszData);
}


CMyString::~CMyString()
{
delete []pszData;
pszData = NULL;
}

// TestString.cpp
#include "stdafx.h"
#include "MyString.h"
#include <iostream.h>

int main(int argc, char* argv[])
{
CMyString str("Hello World!");
int strlen = str.GetLength();
cout<<strlen<<endl;
return 0;
}

程序编译不出错,但是运行出错,错误信息如下:
TestString.cpp
Generating Code...
Linking...
TestString.obj : error LNK2001: unresolved external symbol "public: int __thiscall CMyString::GetLength(void)" (?GetLength@CMyString@@QAEHXZ)
Debug/TestString.exe : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.

TestString.exe - 2 error(s), 0 warning(s)

值得注意的是假如我在类CMyString添加一个成员函数GetInfo()。将程序改为

// MyString.h
#ifndef MY_STRING_H
#define MY_STRING_H

#include <string.h>

class CMyString
{
private:
char *pszData;
public:
CMyString();
CMyString(char *psz);
int GetLength();
void GetInfo();
~CMyString();
};

#endif
// MyString.cpp
#include "stdafx.h"
#include "MyString.h"
#include <iostream.h>

CMyString::CMyString()
{
pszData = new char[20];
}

CMyString::CMyString(char *psz)
{
pszData = new char[20];
strcpy(pszData,psz);
}

inline int CMyString::GetLength()
{
return strlen(pszData);
}

void CMyString::GetInfo()
{
int strlen = GetLength();
cout<<strlen<<endl;
}

CMyString::~CMyString()
{
delete []pszData;
pszData = NULL;
}

// TestString.cpp

#include "stdafx.h"
#include "MyString.h"
#include <iostream.h>

int main(int argc, char* argv[])
{
CMyString str("Hello World!");
int strlen = str.GetLength();
cout<<strlen<<endl;
return 0;
}

在这种情况下即使把inline函数的实现代码可以放在.cpp文件,程序依然能运行成功。这个我实在搞不懂了。我想这是不是VC6.0对C++标准的一个不兼容的地方呢?
...全文
1532 27 打赏 收藏 转发到动态 举报
写回复
用AI写文章
27 条回复
切换为时间正序
请发表友善的回复…
发表回复
jianghaibo8888 2012-03-31
  • 打赏
  • 举报
回复
我看了C++ primer后的理解如下:
我的感觉就是,在这个文件中虽然包含了原有的头文件,但是原有的头文件中的inline并没有被定义(
我们回想一下online函数的初衷:就是在用到它的时候,能够在用到它的地方迅速得展开自己的函数体,用来节省函数调用的时间。就可以理解为替换作用)。
但是我们在本文件中,只包含了原有文件的头文件,并没有包含原有CPP,所以我的理解吧,感觉当online在这个文件中展开时,它找不到自己的函数体。因为原有的头文件中没有定义,它定义在原有文件的CPP文件中。而本文件没有包含原有文件的CPP文件。所以出错了!
表达不是太好,望理解!!!
wangyangkobe 2011-04-02
  • 打赏
  • 举报
回复
inline 函数应放入头文件中,内敛函数的定义必须对编译器是可见的,以便编译器能够在调用点内敛展开该函数的调用,此时,仅有函数原型是不行的。
acange 2007-02-19
  • 打赏
  • 举报
回复
放在头文件中定义,你可以省略 inline
如果你在 cpp 文件中定义, 你必须在前面加 inline

放哪都可
ccraobb 2007-02-18
  • 打赏
  • 举报
回复
我也认为放在头文件中
Mephisto_76 2007-02-14
  • 打赏
  • 举报
回复
理论上可以放到cpp文件中,但是在VC中你在cpp中写一个inline成员方法时,链接器会报错。你只能在h文件中定义。
飞哥 2007-02-13
  • 打赏
  • 举报
回复
哪用放哪
Jofee 2007-02-13
  • 打赏
  • 举报
回复
好像高手都说得很清楚了。
在给新手增加一条:
不要太相信内联,内联函数是否真正成为了内联函数,一般是取决于编译器,而不是我们声明他是inline他就是inline的。
yingyys 2007-02-13
  • 打赏
  • 举报
回复
一般都放在.h中吧
Cocoky 2007-02-13
  • 打赏
  • 举报
回复
当然不在类中的可以随便在哪里定义
Cocoky 2007-02-13
  • 打赏
  • 举报
回复
要么写在类里,不要指明inline,自动为inline,要么在类中声明inline ,在实现文件里定义函数体.
qhgary 2007-02-12
  • 打赏
  • 举报
回复
whoho(在北方流浪)说得很清楚了,不是说不可以,只是需要遵守他说得几个原则,你可以通过很多方法来做,只要符合这个原则就可以了.
但是通常最简单而又不出错的方法就是在.h里面直接写内联函数.
飞驰的青蛙 2007-02-12
  • 打赏
  • 举报
回复
放在.cpp中
Wolf0403 2007-02-12
  • 打赏
  • 举报
回复
whoho 的 principle 是正确的..提一个常见的组织方法

// defs.h
#ifndef DEFS_H
#define DEFS_H

inline void inline_func ();

#include "defs.icc"

#endif // DEFS_H

// defs.icc

void inline_func ()
{
} // 实现放在这个.icc 文件中。这个文件不直接被编译。
OOPhaisky 2007-02-11
  • 打赏
  • 举报
回复
看看Scott Meyers的effective系列,里面好像有几个条款讲到inline的问题,但是手头没有书,不敢确定。。。
axx1611 2007-02-11
  • 打赏
  • 举报
回复
jixingzhong(瞌睡虫·星辰) ( ) 信誉:102 Blog 2007-02-11 09:52:32 得分: 0


inline 函数应当和它的声明 是同一个文件的


-----------------------------------

没这种说法,虽然习惯上如此。

只要你愿意,定义和声明写在多个.h文件也没问题,只要使用者最终都包含它们就行了。

对于不会被外界使用函数,比如私有(不能有friend,或者就算有也不可能用到这些函数),
写在.cpp里也可以,不过没多少必要……
clever101 2007-02-11
  • 打赏
  • 举报
回复
quote:
一般可以在头文件中声明内联函数使用inline关键字,
在cpp文件中定义此函数,不用inline.


不会吧。inline是一种编译实现,即编译时用inline来提高效率,如果在cpp文件中定义此函数不用inline,编译器如何识别呢?
jixingzhong 2007-02-11
  • 打赏
  • 举报
回复
也就是说,
可以不在 class 中定义 inline 函数。
但是应该保证 inline 函数和这个 函数的声明是同一个文件中的 ~~
jixingzhong 2007-02-11
  • 打赏
  • 举报
回复
inline 函数应当和它的声明 是同一个文件的
htqx 2007-02-11
  • 打赏
  • 举报
回复
inline 这个关键字并没有必要一定不生成函数体.
大可以生产函数体,又inline.因为这没有冲突.

我估计都是static默认链接说法这个比较合理.
改成:

inline extern int CMyString::GetLength()
{
return strlen(pszData);
}


magicsutra 2007-02-11
  • 打赏
  • 举报
回复
是的,应该放在头文件中。看C++ Primer。
加载更多回复(7)

64,654

社区成员

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

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