Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >什么时候使用前置声明

什么时候使用前置声明

作者头像
ClearSeve
发布于 2022-02-10 11:03:47
发布于 2022-02-10 11:03:47
88500
代码可运行
举报
文章被收录于专栏:ClearSeveClearSeve
运行总次数:0
代码可运行

问题

什么情况下使用前置声明?

回答

我们可以站在编译器的角度来思考这个问题:当你前置声明一个类型时,编译器就会知道这个类型的存在,但没法知道它的布局、大小、成员…所以我们也把前置声明的类型叫做不完全类型(incomplete type)。

假如你有下面的前置声明,

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class X;

那么你可以做的如下

  1. 定义一个指针或引用 class Foo { X *p; X &r; };
  2. 函数参数或返回值,但没法使用它们的成员变量或函数 void f1(X); X f2(); void f3(X*, X&) X& f4() X* f5()

你不能做的如下

  1. 用作基类 class Foo : X {} // compiler error!
  2. 定义变量 class Foo { X m; // compiler error! }; void f1(X x) {} // compiler error! X f2() {} // compiler error,注意这里有个 {},和上面的是不同的
  3. 无法访问成员变量和成员函数 class Foo { X *m; void method() { m->someMethod(); // compiler error! int i = m->someField; // compiler error! } };

那么模板如何前置声明呢?例如以下的类模板,

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
template<typename Type, typename IDType=typename Type::IDType>
class Mappings
{
public:
    ...
    Type valueFor(const IDType& id) { // return value }
    ...
};

前置声明就是,

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
template<typename Type, typename IDType=typename Type::IDType> // 注意它的默认参数
class Mappings;

C++ 标准容器,例如 std::vector std::list 的前置声明需要加上它的命名空间,例如,

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
namespace std {
  template<class T, class Allocator = std::allocator<T>>
  class list;
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年1月24日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验