c++前向声明设计
c++ Forward Declaration design
根据我所读到的,我应该尽可能使用前向声明。我有这样的类(其中每个字段都是指针,因为向前声明):
class A
{
// ...
A* a;
B* b;
C* c;
D* d;
E* e;
};
但这有问题。
1-这意味着对构造函数中的每个字段调用new和delete(或者至少用智能指针调用new),而堆栈分配的字段不需要这样做。
2-我读到堆栈分配比堆分配快。
3-这也意味着几乎每个类的每个字段都应该是指针。
我做正确的方式做像我的例子类吗?还是我在远期声明中遗漏了什么?
您所展示的示例是多余的。使用前向声明的建议并不意味着您的代码设计是由前向声明实践驱动的。前向声明只是实现细节,以设计为准。
首先决定是需要聚合还是复合,然后再决定前向声明是否合适。
当前向声明的类型是你的方法签名的一部分,即参数的类型时,比#include
更喜欢前向声明。
#include "OtherClass.h" // 'bad' practice
class OtherClass; // this is better than #include
....
class MyClass
{
void method(OtherClass *ptr);
}
这并不是一个绝对的规则,因为使用forward decls代替include并不总是可能/方便的。
含义是相反的——你不应该仅仅为了使用前向声明而使用指针,而应该在你做出设计决定(比如使用指针而不是对象作为成员)之后使用前向声明。
因此,如果使用对象更有意义,那么就这样做,并包含您需要的文件。不要仅仅为了前向声明类而使用指针。
如果使用指针作为成员,最好是前向声明,而不是公开完整的类定义。不要为了满足某些规则而盲目地使用指针。
从技术上讲,如果类的接口不依赖于完全限定类型,则可以(而且应该)使用前向声明。编译器必须为成员保留足够的空间,并在编译时添加管理函数——仅仅在类中使用指针或引用不会引入对类型的依赖。
BTW:前向声明不是那么新:在一些C标准库中,FILE
是前向声明的struct
的typedef
,这是有意义的,因为FILE
总是用于整个公共文件API中的指针
对不属于类的对象使用指针或引用。但是对于该类拥有的对象,不要使用前向声明作为选择指针的理由。
如果你真的想最小化编译时的依赖关系,考虑使用PIMPL模式,而不是把所有的成员都变成指针:
MyClass.h:
#include <memory>
class MyClassImpl;
class MyClass {
public:
MyClass();
~MyClass();
void doThing();
private:
std::unique_ptr<MyClassImpl> pimpl_;
};
MyClass.cpp
#include "MyClass.h"
#include "MyClassImpl.h"
MyClass::MyClass() { } // in .cpp so unique_ptr constructor has complete type
MyClass::~MyClass() { } // in .cpp so unique_ptr destructor has complete type
void MyClass::doThing(){
pimpl_->doThing();
}
MyClassImpl.h:
#include "A.h"
#include "B.h"
class MyClassImpl {
private:
A a_;
B b_;
public:
void doThing();
};
MyClassImpl.cpp:
#include "MyClassImpl.h"
void MyClassImpl::doThing() {
// Do stuff with a_, b_, etc...
}
这可能不会解决性能问题,因为您仍然有动态内存分配,但您必须测量它才能看到。
除了已经给出的好答案之外:在您的类不创建对象但私下使用它的情况下(例如某些实用程序类),可以使用引用代替指针。
class UtilityClass; // forward declaration (even interfaces make sense here)
class MyClass {
public:
/// takes an UtilityClass for implementing some of its functions
MyClass(UtilityClass& u): util(u) {}
private:
UtilityClass& util;
// ...more details
};
在这些情况下,前向声明并不意味着必须在堆上创建对象(就像您的问题#1和#2一样)。
- .cpp和.h文件中的模板专用化声明
- 未在作用域中声明unordered_map
- C++避免重复声明的语法是什么
- 如何确保C++函数在定义之前声明(如override关键字)
- 错误:未在此范围内声明'reverse'
- 奇怪的(对我来说)返回声明 - 在谷歌上找不到任何关于它的信息
- 为什么在定义函数之前先声明它
- 如何声明特征矩阵,然后通过嵌套循环初始化它
- #ifdef和未声明的标识符
- 没有显式声明的int[]中的foreach
- 在基于范围的for循环中使用结构化绑定声明
- 在将变量声明为引用时,堆在释放后使用
- C++:无法访问声明的受保护成员
- 为什么我不能在一个类的不同行中声明和定义成员变量?
- 我不明白为什么我声明一个空的内部结构并将其传递给构造函数
- 使用cmake从源代码构建MySQL连接器/C++失败(与以前的声明冲突)
- 在函数内部的声明中初始化数组,并在外部使用它
- Visual Studio中的函数声明和函数定义问题
- c++类声明时,相同的例程,不同的成员变量类型
- 在 .h 文件中的类中声明静态变量和在.cpp文件中声明"global"变量有什么区别