在哪里放置函数声明?
Where to put function declaration?
假设我正在开发一个日志记录功能。在logging.h
里面,我声明了应用程序稍后要使用的函数。
// logging.h
#include <string>
namespace logging {
void LogThis(const std::string& text);
}; // namespace logging
它的定义显然在logging.cpp
里面:
// logging.cpp
void logging::LogThis(const std::string& text) {
std::cout << "Log: " << text << 'n';
}
现在让我们假装我的LogThis
函数的工作被拆分为一些较小的帮助程序函数。它们不是日志记录接口的一部分。让我们以Prettify
函数为例。
// logging.cpp
void logging::LogThis(const std::string& text) {
Prettify(text);
std::cout << "Log: " << text << 'n';
}
我的问题是:我把Prettify
的函数声明放在哪里?我不应该将它包含在logging.h
头文件中,因为这样它就可以被其他编译单元调用,并且它不是接口的一部分。所以就这样把它放在logging.cpp
里面吗?
// logging.cpp
namespace logging {
void Prettify(std::string& ugly_text);
void LogThis(const std::string& text) {
Prettify(text);
std::cout << "Log: " << text << 'n';
}
void Prettify(std::string& ugly_text) {
// making it pretty...
}
}
我正在寻找一些关于此:)的最佳实践/经验法则/意见提前感谢!
对于文件中只需要的东西,我只是将其放在C++文件本身的匿名命名空间中,有点像 functions(a(上的旧版 Cstatic
关键字的现代等价物:
namespace {
void WeaveMagic(std::string& ugly_text) {
WeaveMoreMagic(ugly_text);
}
void Prettify(std::string& ugly_text) {
WeaveMagic(ugly_text);
}
}
如果在使用函数之前放置此值,并确保调用的严格层次结构,则可以跳过声明,因为定义提供了所需的信息,如上所示。
当然,如果多个匿名函数之间存在任何循环依赖关系(即循环递归(,您仍然需要提供声明:
#include <iostream>
namespace {
int DivThree(int val); // needed to implement AddOne()
int AddOne(int val) {
std::cout << "AddOne " << val << " -> " << (val + 1) << 'n';
if (val > 0) return DivThree(val + 1);
return val;
}
int DivThree(int val) {
std::cout << "DivThree " << val << " -> " << (val / 3) << 'n';
return AddOne(val / 3);
}
}
int main(){
int final = AddOne(18);
std::cout << "Final " << final << 'n';
return 0;
}
而且,是的,这是非常人为的,但是循环递归的好例子很少而且相距甚远:-(输出为:
AddOne 18 -> 19
DivThree 19 -> 6
AddOne 6 -> 7
DivThree 7 -> 2
AddOne 2 -> 3
DivThree 3 -> 1
AddOne 1 -> 2
DivThree 2 -> 0
AddOne 0 -> 1
Final 0
(a(CPP Core Guidline SF.22实际上涵盖了以下内容:
对所有内部/非导出实体使用未命名(匿名(命名空间。
原因:任何外部内容都不能依赖于嵌套的未命名命名空间中的实体。请考虑将实现源文件中的每个定义放在未命名的命名空间中,除非该定义定义"外部/导出"实体。
API 类及其成员不能位于未命名的命名空间中;但在实现源文件中定义的任何"帮助程序"类或函数都应位于未命名的命名空间范围内。
如果你只对函数进行操作,正如@paxdiablo所写的那样,你可以使用匿名命名空间(看看他的回答(。
我有一些基于C的习惯,所以我个人也会将其视为static
功能。但我不确定C++狂热分子:)会如何看待它。static
(在此上下文中(使编译单元(logging.cpp(的函数在本地,因此无法从外部链接。
//logging.cpp
static void Prettify(std::string& ugly);
void LogThis(const std::string& text) {
Prettify(text);
std::cout << "Log: " << text << 'n';
}
static void Prettify(std::string& ugly) { }
但是,如果您的日志记录实用程序是面向对象的。我建议你使用D指针和Q指针设计模式(也称为PImpl习语( - https://en.cppreference.com/w/cpp/language/pimpl 。
//logging.h
#include <string>
class loggingImpl;
class logging {
public :
logging();
virtual ~logging();
void LogThis(const std::string& text);
protected :
loggingImpl *impl;
};
//logging.cpp
class loggingImpl
{
public :
loggingImpl(logging *p) : qptr(p) { }
void Prettify(std::string& ugly) { }
//anything what you need and should be hided
// access parent through qptr
protected :
logging *qptr;
};
logging::logging() : impl(new loggingImpl) { }
logging::~logging() { delete impl; }
void logging::LogThis(const std::string& text) {
impl->Prettify(text);
std::cout << "Log: " << text << 'n';
}
正如您所写的,由于限制了未使用符号的可见性,将声明放在头文件中是不正确的。
- C++:为什么允许在另一个函数中声明函数,而不允许在函数定义中声明?
- 在c++中在类外声明函数有什么好处
- 使用 #define 声明函数
- 在静态库中声明函数,在使用该相同库的应用程序中定义它
- 如何强制编译器在 C/C++ 本身中声明函数?
- 如果您只需要在 .h 文件中声明函数.cpp是否需要在 .h 文件中声明函数?
- C++:<sys/sysctl.h> 无法声明函数CTL_HW和HW_NCPU
- 尝试声明函数的局部变量,但得到范围错误
- 如何在C++模板中声明函数
- 如何在另一个文件的类中声明函数
- 使用非类型模板参数正向声明函数模板
- 在此范围错误中未声明函数错误
- 当我们不能声明函数内联(GCC 编译器)时?
- 未在此作用域中声明函数,即使存在头文件也是如此
- 无法声明函数中的模板类型别名
- 单个CPP文件中多次声明函数声明可以吗?
- 编译一个支持VBA中声明函数的dll
- 使用从外部参数包中获取的参数类型声明函数
- 使用类成员正确地声明函数
- 在函数内重新声明函数