5

我更喜欢#include在我的头文件中尽量减少使用,尽可能使用前向声明,我相信这被认为是好的做法。

如果我有一个方法声明,它会很好用:

bool IsFlagSet(MyObject *pObj);

但是,如果我有typedef Ptr<MyObject> MyObjectPtr并且MyObject.hAPI 更改为:

bool IsFlagSet(MyObjectPtr pObj);

我现在不需要#include "MyObject.h"?有没有办法解决这个问题,或者仅仅是使用智能指针所付出的代价?

4

3 回答 3

9

不,您不必这样做。您可以为不完整的类定义类型别名,模板参数可以是不完整的类型(请参阅 C++11 标准的第 14.3.1/2 段):

#include <memory>

struct C;

typedef std::shared_ptr<C> ptrC; // C is incomplete here

struct C { void foo() { } };

int main()
{
    ptrC p = std::make_shared<C>();
    p->foo();
}

正如Pubby在评论中正确提到的那样,函数声明也不要求其签名中提到的类型是完整的:

struct C;

void foo(C); // C is incomplete here

struct C { };

#include <iostream>

void foo(C)
{
    std::cout << "foo(C)" << std::endl;
}

int main()
{
    C c;
    foo(c);
}
于 2013-03-22T15:05:08.870 回答
3

不,std::shared_ptr<T>明确设计T为仅在前向声明时工作。当然,这并不适用于所有情况,但原理与普通指针相同。如果T是前向声明的,你可以做任何你可以做std::shared_ptr<T>的事情T*

于 2013-03-22T15:07:21.040 回答
0

您可以将 typedef 与不完整的类型一起使用。

但是使用智能指针类型的全名不是更好吗?

MyClassPtr当然要短得多,但std::unique_ptr<MyClass>实际上告诉我们如何使用这个指针。因此,对于不是很长的名称,我建议使用智能指针的全名。

于 2013-03-22T15:11:15.970 回答