c++ inline使函数实现可以在头文件中,避免多重定义错误

谨慎使用 static:如果只是想把函数定义写在头文件中,用 inline,不要用static。static 和 inline 不一样:

  1. static 的函数是内部链接,不同编译单元可以有同名的static 函数,但该函数只对 对应的编译单元 可见。如果同一定义的 static 函数,被不同编译单元调用,每个编译单元有自己单独的一份拷贝,且此拷贝只对 对应的编译单元 可见。
  2. inline 的函数是 external linkage,如果被不同编译单元调用,每个编译单元引用/链接的是同一函数,同一定义。
  3. 上面的不同直接导致:如果函数内有 static 变量,对inline 函数,此变量对不同编译单元是共享的(Meyer’s Singleton);对于static 函数,此变量不是共享的。看后面的代码就明白区别了。

static inline 函数,跟 static 函数单独没有差别,所以没有意义,只会混淆视听。

inline 函数的定义不一定要跟声明放在一个头文件里面:定义可以放在一个单独的头文件 .hxx 中,里面需要给函数定义前加上 inline 关键字,原因看下面第 2.点;然后声明 放在另一个头文件 .hh 中,此文件include 上一个 .hxx。这种用法 boost里很常见:优点1. 实现跟API 分离,encapsulation。优点2. 可以解决 有关inline 函数的循环调用问题:这个不展开说了,看一个这个文章就懂了:Headers and Includes: Why and How 第 7 章,function inlining。

指定inline

  1. 不要再把 inline 和编译器优化挂上关系了,不加inline,小函数编译器也会自动优化,看到inline时,应该首先想到其他用意,再考虑编译器优化。
  2. inline最大的用处是:非template 函数,成员或非成员,把定义放在头文件中,定义前不加inline ,如果头文件被多个cpp文件引用,编译会报错重定义。

static_inline_A.h文件:

#ifndef __STATIC_INLINE_A__
#define __STATIC_INLINE_A__

# include <iostream>

namespace static_test
{
	volatile static int a = 10;
	inline int& static_value() // (!*!) Or change this to inline
	{
		static int value = -1;
		return value;
	}

	namespace A
	{
		void set_value(int val);
		void print_value();
		
		void set_static_value(int val);
		void print_static_value();
	}
}

#endif  // __STATIC_INLINE_A__

static_inline_A.cpp文件:

# include "static_inline_A.h"

namespace static_test
{
	namespace A
	{
		void set_value(int val)
		{
			auto& value = static_value();
			value = val;
		}

		void print_value()
		{
			std::cout << static_value() << '\n';
		}

		void set_static_value(int val)
		{
			a = val;
		}

		void print_static_value()
		{
			std::cout << "A::a = " << a << std::endl;
		}
	}
}

static_inline_B.h文件:

#ifndef __STATIC_INLINE_B__
# define __STATIC_INLINE_B__

# include <iostream>

namespace static_test
{
	namespace B
	{
		void set_value(int val);
		void print_value();

		void set_static_value(int val);
		void print_static_value();
	};
}

#endif  // __STATIC_INLINE_B__

static_inline_B.cpp文件:

# include "static_inline_A.h"
# include "static_inline_B.h"

namespace static_test
{
	namespace B
	{
		void set_value(int val)
		{
			auto& value = static_value();
			value = val;
		}

		void print_value()
		{
			std::cout << static_value() << '\n';
		}

		void set_static_value(int val)
		{
			a = val;
		}

		void print_static_value()
		{
			std::cout << "B::a = " << a << std::endl;
		}
	}
}

测试代码:

# include "static_inline_A.h"
# include "static_inline_B.h"

int main()
{
	static_test::A::set_value(42);

	static_test::A::print_value();
	static_test::B::print_value();

	static_test::B::set_value(37);

	static_test::A::print_value();
	static_test::B::print_value();


	static_test::A::set_static_value(100);

	static_test::A::print_static_value();
	static_test::B::print_static_value();

	static_test::B::set_static_value(200);

	static_test::A::print_static_value();
	static_test::B::print_static_value();

	system("pause");
	return 0;
}

输出:
在这里插入图片描述
注意:定义静态变量也是一样,在不同的文件引用会产生不同的静态变量。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值