我更喜欢尽可能地使用前向声明来最小化我的头文件中#include
的使用,我相信这被认为是一种很好的做法。
如果我有一个方法声明,那么它很有用:
bool IsFlagSet(MyObject *pObj);
但是,如果typedef Ptr<MyObject> MyObjectPtr
中有MyObject.h
且API已更改为:
bool IsFlagSet(MyObjectPtr pObj);
我现在 到#include "MyObject.h"
了吗?有没有办法解决这个问题,还是仅仅是使用智能指针付出的代价?
答案 0 :(得分: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);
}
答案 1 :(得分:3)
不,std::shared_ptr<T>
明确设计为仅在T
向前声明时才有效。当然,这并不适用于所有情况,但原理与普通指针相同。如果T
是向前声明的,您可以使用std::shared_ptr<T>
对T*
执行任何操作。
答案 2 :(得分:0)
你可以使用不完整类型的typedef。
但使用智能指针类型的全名是不是更好?
MyClassPtr
当然要短得多,但std::unique_ptr<MyClass>
实际上告诉我们如何使用这个指针。因此,对于不长的名称,我建议使用智能指针的全名。