Deprecated: imwpcache\f884414bce24ee67f\f73723ec7b1919fa5::__construct(): Implicitly marking parameter $YECBGYFECGEAFWHA as nullable is deprecated, the explicit nullable type must be used instead in /www/wwwroot/www.chuangxiangniao.com/wp-content/plugins/imwpcache-dist/build/f884414bce24ee67ff73723ec7b1919fa5.php on line 2

Deprecated: imwpcache\f884414bce24ee67f\f73723ec7b1919fa5::__construct(): Implicitly marking parameter $BBWFDDBHHYHDXXAB as nullable is deprecated, the explicit nullable type must be used instead in /www/wwwroot/www.chuangxiangniao.com/wp-content/plugins/imwpcache-dist/build/f884414bce24ee67ff73723ec7b1919fa5.php on line 2
C++中结构体能否继承 对比结构体与类的继承特性差异_创想鸟

C++中结构体能否继承 对比结构体与类的继承特性差异

c++++中结构体支持继承,其与类的主要区别在于默认的成员访问权限和继承方式。1. 结构体默认成员是公开的,默认继承也是公开的;2. 类默认成员是私有的,默认继承也是私有的。两者在功能上几乎等价,但struct更适用于数据聚合,class强调封装。例如,在事件处理系统中,使用结构体继承表达数据为主的多态关系更为直观。最佳实践包括:明确表达设计意图、优先使用class并显式指定继承方式、保持项目风格一致。

C++中结构体能否继承 对比结构体与类的继承特性差异

是的,C++中的结构体完全支持继承,与类在继承机制上几乎没有本质区别。它们的主要差异体现在默认的成员访问权限和默认的继承访问权限上。简单来说,如果你不明确指定,结构体默认成员是公开的,继承也是公开的;而类默认成员是私有的,继承也是私有的。

C++中结构体能否继承 对比结构体与类的继承特性差异

解决方案

C++中的结构体(struct)和类(class)在继承机制上是等价的,它们都可以作为基类被继承,也可以继承其他基类。这背后其实是语言设计上的一个巧妙统一:struct本质上就是class,只不过struct默认的成员访问权限是public,而class默认的成员访问权限是private。同样的逻辑也延伸到了继承上。

C++中结构体能否继承 对比结构体与类的继承特性差异

来看一个例子,这能更直观地说明问题:

立即学习“C++免费学习笔记(深入)”;

#include #include // 基结构体struct BaseStruct {    int id;    std::string name;    BaseStruct(int i, const std::string& n) : id(i), name(n) {        std::cout << "BaseStruct constructor called." << std::endl;    }    void printBaseInfo() const {        std::cout << "ID: " << id << ", Name: " << name << std::endl;    }};// 派生结构体,默认是公共继承struct DerivedStruct : BaseStruct { // 等同于 struct DerivedStruct : public BaseStruct    double value;    DerivedStruct(int i, const std::string& n, double v)        : BaseStruct(i, n), value(v) {        std::cout << "DerivedStruct constructor called." << std::endl;    }    void printDerivedInfo() const {        printBaseInfo(); // 可以直接访问基类的公共成员        std::cout << "Value: " << value << std::endl;    }};// 基类class BaseClass {private:    int internalId; // 默认私有public:    std::string className;    BaseClass(int i, const std::string& n) : internalId(i), className(n) {        std::cout << "BaseClass constructor called." << std::endl;    }    void printClassName() const {        std::cout << "Class Name: " << className << ", Internal ID: " << internalId << std::endl;    }};// 派生类,默认是私有继承class DerivedClass : BaseClass { // 等同于 class DerivedClass : private BaseClasspublic: // 需要显式声明为public才能在外部访问    double version;    DerivedClass(int i, const std::string& n, double v)        : BaseClass(i, n), version(v) {        std::cout << "DerivedClass constructor called." << std::endl;    }    void printVersionInfo() const {        // printClassName(); // 编译错误:因为BaseClass是私有继承,其public成员在DerivedClass中变为private        // 如果想访问基类的公共方法,需要将其在DerivedClass中提升访问权限,或者通过DerivedClass的成员方法间接调用        std::cout << "Version: " << version << std::endl;    }};// 如果想让类也像结构体一样默认公共继承,需要显式指定class AnotherDerivedClass : public BaseClass {public:    double rating;    AnotherDerivedClass(int i, const std::string& n, double r)        : BaseClass(i, n), rating(r) {}    void printRatingInfo() const {        printClassName(); // 可以访问,因为是公共继承        std::cout << "Rating: " << rating << std::endl;    }};// int main() {//     DerivedStruct ds(1, "MyStruct", 10.5);//     ds.printDerivedInfo();//     std::cout << std::endl;//     // DerivedClass dc(2, "MyClass", 2.0);//     // dc.printVersionInfo();//     // dc.printClassName(); // 编译错误,因为是私有继承//     AnotherDerivedClass adc(3, "AnotherClass", 4.8);//     adc.printRatingInfo();//     adc.printClassName(); // 可以访问//     return 0;// }

从上面的代码片段可以看出,结构体和类在语法上都支持继承,关键在于理解它们各自的默认行为。

C++中结构体能否继承 对比结构体与类的继承特性差异

C++结构体与类的继承默认行为有何不同?

核心差异在于默认的继承访问权限。当你声明一个派生类或派生结构体,但没有明确指定继承方式(public、protected或private)时,编译器会根据你是使用struct还是class来决定:

结构体(struct)的默认继承是 public:如果你写 struct Derived : Base { ... };,这等价于 struct Derived : public Base { ... };。这意味着Base的所有public成员在Derived中依然是public,protected成员依然是protected。这种行为通常符合我们对“是一个(is-a)”关系的直观理解,即派生类型完全继承了基类型的接口。

类(class)的默认继承是 private:如果你写 class Derived : Base { ... };,这等价于 class Derived : private Base { ... };。这意味着Base的所有public和protected成员在Derived中都变成了private。这是一种更强的封装,通常用于实现“基于(implemented-in-terms-of)”的关系,即派生类内部使用了基类的功能,但基类的接口不应该暴露给派生类的外部用户。

这种默认行为的选择,是C++设计者基于历史和惯用法的一个权衡。struct在C语言中是纯粹的数据聚合,引入C++后,为了兼容C并保持其数据聚合的语义,默认访问权限和继承权限都倾向于“开放”。而class则从一开始就强调封装和信息隐藏,所以默认权限更倾向于“封闭”。

结构体继承在实际项目中有什么应用场景?

虽然类在面向对象设计中更为常见,但结构体继承在某些特定场景下也能发挥其作用,尤其当强调数据聚合和轻量级多态时:

数据结构的多态变体:当你的设计中需要一组相关的数据结构,它们共享一些共同的字段,但又各自有一些特有的字段时,结构体继承可以很好地表达这种关系。例如,在事件处理系统中,你可能有一个struct Event作为基类,然后派生出struct MouseEvent : Event、struct KeyEvent : Event等。这些事件通常以数据为主,可能只包含少量虚函数用于处理。

struct BaseEvent {    enum Type { Unknown, Mouse, Keyboard };    Type type;    virtual ~BaseEvent() = default; // 允许多态销毁    virtual void process() const = 0;};struct MouseEvent : BaseEvent {    int x, y;    MouseEvent(int px, int py) : x(px), y(py) { type = Mouse; }    void process() const override {        std::cout << "Processing MouseEvent at (" << x << ", " << y << ")" << std::endl;    }};struct KeyEvent : BaseEvent {    int keyCode;    KeyEvent(int kc) : keyCode(kc) { type = Keyboard; }    void process() const override {        std::cout << "Processing KeyEvent with code " << keyCode << std::endl;    }};

这种情况下,结构体的使用强调了这些类型主要是数据容器的本质。

轻量级协议或消息格式:在网络通信或序列化场景中,消息通常是结构化的二进制数据。如果这些消息有共通的头部,而具体内容根据消息类型不同,那么使用结构体继承来定义这些消息格式是非常自然的。基结构体定义通用头部,派生结构体定义特定消息体。由于这些结构体往往直接映射到内存布局,使用struct在语义上更贴切。

遵循“数据即结构体,行为即类”的惯例:C++社区中有一个非官方但广泛接受的惯例:struct用于表示纯粹的数据聚合(Plain Old Data, POD)或主要由数据组成的对象,而class则用于表示具有复杂行为、封装和不变量的抽象实体。当你的继承层次结构主要是为了共享数据字段或提供轻量级多态时,使用struct可以更好地传达这种意图。这使得代码的意图更加清晰,尤其是在大型项目中,这种约定能帮助开发者更快地理解代码的用途。

在C++中,选择结构体还是类进行继承的最佳实践是什么?

在C++中,选择struct还是class进行继承,更多的是一种风格和意图的表达,而不是功能上的严格限制。毕竟,它们在功能上几乎是等价的,你总可以通过显式指定访问修饰符来达到相同的效果。

我的看法是:

明确表达意图:

使用class进行继承,并显式指定继承方式(public、protected、private):这是最清晰、最推荐的做法。当你使用class时,你通常是在构建一个复杂的对象模型,强调封装和行为。显式指定继承方式,可以避免依赖默认规则,使代码意图一目了然,无论是public(“是一个”关系)还是private(“基于”关系)。使用struct进行继承,当你主要关注数据聚合和轻量级多态时:如果你的类型主要是为了组织数据,并且继承是为了共享数据字段或提供简单的多态接口(例如,上述的事件系统),那么使用struct可以更好地传达这种“数据结构”的语义。在这种情况下,struct默认的public继承通常也符合你的期望。

遵循“数据即结构体,行为即类”的经验法则:这个法则虽然不是强制性的,但在实践中很有指导意义。如果你的基类型和派生类型主要是数据容器,并且方法很少或只是简单的存取器,那么使用struct。如果它们拥有复杂的业务逻辑、内部状态管理、不变量,或者需要严格的封装,那么class是更合适的选择。这个法则也自然延伸到继承上:如果继承是为了共享数据结构,struct可能更直观;如果继承是为了构建复杂的面向对象层次结构,class是标准做法。

保持一致性:在一个项目中,或者一个模块内部,选择一种风格并保持一致性至关重要。如果你的团队已经习惯了所有继承都使用class并显式指定继承方式,那就继续这样做。如果你们的库中大量使用struct来表示数据消息,并在此基础上进行继承,那也应该遵循这个模式。一致性可以大大降低代码的认知负担。

总而言之,虽然struct和class在继承上功能几乎一致,但它们各自的默认行为和社区惯例赋予了它们不同的语义倾向。理解这些倾向,并根据你的设计意图和团队约定来选择,是编写清晰、可维护C++代码的关键。在不确定时,使用class并显式指定继承方式通常是最稳妥的选择。

以上就是C++中结构体能否继承 对比结构体与类的继承特性差异的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1466795.html

赞 (0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
C++中模块模式如何组织代码 命名空间与匿名命名空间的合理运用
上一篇 2025年12月18日 16:13:31
Golang的channel有哪些使用模式 解析生产者消费者案例
下一篇 2025年12月18日 16:13:42

相关推荐

  • 这台五万元的相机,哈苏想卖给「普通人」

    这台五万元的相机,哈苏想卖给「普通人」这台五万元的相机,哈苏想卖给「普通人」这台五万元的相机,哈苏想卖给「普通人」这台五万元的相机,哈苏想卖给「普通人」

    拍照,可能是这个时代门槛最低的创作行为了。 我们每天都在生产和消费着海量的图片,记录变得前所未有地容易,但容易,就等于好吗? 过去,哈苏的答案是倾向于「好」,但代价是「难」——你需要理解光圈、快门,要背着沉重的三脚架,甚至要在特定的拍摄环境中,才能驾驭这份极致的画质。 在推出了备受瞩目的 X2D 1…

    2026年9月25日 • 用户投稿
    200
  • C语言判断素数方法

    C语言判断素数方法C语言判断素数方法C语言判断素数方法C语言判断素数方法

    求素数的问题通常可以划分为两大类。 1、解决素数相关问题常用的方法主要有两种。 2、判断某个给定的数是否为质数。 3、找出所有小于指定数值的质数。 4、核心概念包括:素数是大于1且只能被1和其本身整除的自然数。要判断一个数是否为素数,可以通过尝试用从2到该数减1的所有整数去除它,若发现有能整除的因子…

    2026年9月25日 • 用户投稿
    700
  • 豆包是否可以本地部署 自主可控环境下运行豆包的技术路径说明

    本文旨在解答关于豆包是否可以在本地环境下进行部署并实现自主可控运行的问题。目前,豆包主要以云服务形式提供,用户通过网络访问其功能。要在自主可控的环境下运行类似的大型语言模型能力,通常需要采用不同的技术路径,即在本地计算资源上部署可用的AI模型。本文将概述实现本地自主可控AI运行的通用技术路线和关键步…

    2026年9月25日
    300
  • 荣耀 300 系列系统升级,后续多款新机待发

    荣耀 300 系列系统升级,后续多款新机待发荣耀 300 系列系统升级,后续多款新机待发荣耀 300 系列系统升级,后续多款新机待发荣耀 300 系列系统升级,后续多款新机待发

    日前,荣耀 300 系列手机迎来 magicos 9.0.0.187 版本升级,此次更新带来了清理建议、ai 通话等多项新功能,系统升级将以分批推送的形式逐步覆盖用户。 本次更新的主要亮点如下: 图库方面新增“清理建议”功能,可智能识别重复照片、相似图片及超大视频,帮助用户更高效地管理存储空间; 通…

    2026年9月25日 • 用户投稿
    500
  • PHP文件引入时参数传递机制详解与最佳实践

    在php中,直接通过url查询字符串方式向`require`或`include`引入的文件传递参数是无效的,这会导致“未定义变量”错误。本文将深入探讨php文件引入的原理,并提供三种正确的参数传递方法:利用作用域共享、手动填充`$_get`数组,以及推荐的通过函数或类进行封装,旨在帮助开发者构建更健…

    2026年9月25日
    000
  • sublime怎么设置字体和字号 _sublime字体与字号调整方法

    sublime怎么设置字体和字号 _sublime字体与字号调整方法sublime怎么设置字体和字号 _sublime字体与字号调整方法sublime怎么设置字体和字号 _sublime字体与字号调整方法sublime怎么设置字体和字号 _sublime字体与字号调整方法

    先修改用户设置文件以调整字体和字号,打开Preferences → Settings,在右侧User配置中添加”font_face”和”font_size”选项,如{“font_face”: “Fira Code&#…

    2026年9月25日 • 用户投稿
    000
  • Java 8 使用 Stream API 扁平化嵌套 Map 并提取首个元素

    Java 8 使用 Stream API 扁平化嵌套 Map 并提取首个元素Java 8 使用 Stream API 扁平化嵌套 Map 并提取首个元素Java 8 使用 Stream API 扁平化嵌套 Map 并提取首个元素Java 8 使用 Stream API 扁平化嵌套 Map 并提取首个元素

    本文将详细介绍如何使用 Java 8 的 Stream API 将一个嵌套的 Map 结构进行扁平化处理,并从中提取所需的数据。 具体来说,我们将把 Map<Integer, Map<String, List>> 转换为 Map,其中新 Map 的键是原内部 Map 的键,值…

    2026年9月25日 • 用户投稿
    1200
  • 首个对话式音乐创作 Agent“Tunee”正式公测

    首个对话式音乐创作 Agent“Tunee”正式公测首个对话式音乐创作 Agent“Tunee”正式公测首个对话式音乐创作 Agent“Tunee”正式公测首个对话式音乐创作 Agent“Tunee”正式公测

    趣丸科技旗下天谱乐团队自主研发的国内首款对话式音乐创作agent“tunee”近日正式启动全球公测,全面向公众开放使用。 据悉,用户只需通过自然语言描述自己的音乐设想,即便表达模糊,Tunee也能自动完成需求解析、方案设计到实际作曲的完整流程,最终输出契合用户意图的原创音乐作品。 Tunee采用先进…

    2026年9月25日 • 用户投稿
    500
  • Debian syslog如何定制报警机制

    Debian syslog如何定制报警机制Debian syslog如何定制报警机制Debian syslog如何定制报警机制Debian syslog如何定制报警机制

    本文介绍如何在Debian系统中定制syslog报警机制,利用rsyslog实现更灵活的日志监控和告警。 首先,确保已安装rsyslog: sudo apt-get updatesudo apt-get install rsyslog 接下来,修改rsyslog配置文件,/etc/rsyslog.c…

    2026年9月25日 • 用户投稿
    100
  • 对话逐际动力张巍:造机器人很容易,关键是用起来

    对话逐际动力张巍:造机器人很容易,关键是用起来对话逐际动力张巍:造机器人很容易,关键是用起来对话逐际动力张巍:造机器人很容易,关键是用起来对话逐际动力张巍:造机器人很容易,关键是用起来

    “让天下没有难落地的机器人。” 在这样向量子位表达定位和使命后,逐际动力”解释了”为何会成为阿里投资的第一家具身智能机器人公司。 在这样解释定位和使命后,量子位大概感受到了逐际动力被投资的原因—— 至少是成为阿里第一个具身智能投资项目的原因。 实际上,…

    2026年9月25日 • 用户投稿
    500
  • 修改 Android KeyStore 中 KeyPair 的用途

    修改 Android KeyStore 中 KeyPair 的用途修改 Android KeyStore 中 KeyPair 的用途修改 Android KeyStore 中 KeyPair 的用途修改 Android KeyStore 中 KeyPair 的用途

    本文档介绍了如何在 Android KeyStore 中修改现有 KeyPair 的用途,使其支持密钥协商 (Key Agreement) 操作。通过示例代码展示了如何利用 KeyStore.setEntry 方法在 Android 13 (API 33) 及以上版本中导入 KeyPair 并设置所…

    2026年9月25日 • 用户投稿
    600
  • 专业横评便携微单:佳能R50V凭6K超采样+精准快速追焦 成 8000 元内全能首选

    专业横评便携微单:佳能R50V凭6K超采样+精准快速追焦  成 8000 元内全能首选专业横评便携微单:佳能R50V凭6K超采样+精准快速追焦  成 8000 元内全能首选专业横评便携微单:佳能R50V凭6K超采样+精准快速追焦  成 8000 元内全能首选专业横评便携微单:佳能R50V凭6K超采样+精准快速追焦  成 8000 元内全能首选

    随着旅行摄影与短视频创作的需求激增,便携微单已成为多数用户的核心影像工具。面对 8000元以下微单市场的繁杂选择,专业影像评测团队通过150小时实测(涵盖画质解析力、防抖稳定性、低光对焦等 15 项核心指标),结合近万份用户口碑反馈,筛选出 3 款高潜力机型。其中佳能 R50V 凭借“画质无短板、便…

    2026年9月25日 • 用户投稿
    200
  • AI Overviews是否具备个性化推荐机制 个性推荐背后的逻辑与调整方法

    AI Overviews是否具备个性化推荐机制 个性推荐背后的逻辑与调整方法AI Overviews是否具备个性化推荐机制 个性推荐背后的逻辑与调整方法AI Overviews是否具备个性化推荐机制 个性推荐背后的逻辑与调整方法AI Overviews是否具备个性化推荐机制 个性推荐背后的逻辑与调整方法

    AI Overviews在提供信息摘要时,确实融入了个性化推荐机制。本文将深入探讨这一机制的原理、其背后的逻辑以及用户可能影响或理解其个性化倾向的一些方法。我们将分步骤解析这一过程,帮助用户更好地理解和利用AI Overviews的功能。 ☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无…

    2026年9月25日 • 用户投稿
    000
  • quick与quickly用法区别解析

    quick与quickly用法区别解析quick与quickly用法区别解析quick与quickly用法区别解析quick与quickly用法区别解析

    1、 null 2、 词性不同 3、 quick作为形容词,意为速度快、反应灵敏、时间短或动作快捷。 4、 quickly是副词,用来描述动作的迅速进行,也可表示事情很快发生、不久之后或即刻执行。 5、 侧重点不同 6、 quick既可作定语修饰名词,也可在句中作表语使用。 7、 quickly可用…

    2026年9月25日 • 用户投稿
    300
  • 并发处理共享列表并收集结果的方案

    并发处理共享列表并收集结果的方案并发处理共享列表并收集结果的方案并发处理共享列表并收集结果的方案并发处理共享列表并收集结果的方案

    本文旨在介绍如何利用 Java 并行流高效地处理大型列表,尤其是在每个元素的处理过程耗时较长的情况下。并行流能够将列表分割成多个子任务,并在多个线程上并发执行,从而显著提升处理速度。但同时,并发编程也带来了共享资源同步的问题,需要谨慎处理。 使用并行流并发处理列表 假设我们有一个 Foo 类,其 p…

    2026年9月25日 • 用户投稿
    000
  • qq浏览器提示Flash版本过低怎么办 QQ浏览器Flash插件过时问题解决方案

    qq浏览器提示Flash版本过低怎么办 QQ浏览器Flash插件过时问题解决方案qq浏览器提示Flash版本过低怎么办 QQ浏览器Flash插件过时问题解决方案qq浏览器提示Flash版本过低怎么办 QQ浏览器Flash插件过时问题解决方案qq浏览器提示Flash版本过低怎么办 QQ浏览器Flash插件过时问题解决方案

    优先通过QQ浏览器内置插件更新Flash,依次检查设置、使用修复工具、排除安全软件干扰,必要时在可信环境手动安装最新版Flash Player并及时卸载以确保安全。 如果您在使用QQ浏览器访问依赖Flash内容的网页时,收到“Flash版本过低”或插件过时的提示,这通常是因为浏览器内置的Flash插…

    2026年9月25日 • 用户投稿
    200
  • 参加PHP+MySQL就业培训后能获得的岗位有哪些

    参加php+mysql就业培训后,你可以获得以下岗位:1. web开发工程师,利用php和mysql开发动态网站和web应用程序;2. 后端开发工程师,使用php构建后端服务和api;3. 全栈开发工程师,结合前端技术进行全站开发;4. 数据库管理员,负责mysql数据库的设计、优化和维护;5. 软…

    2026年9月25日
    400
  • 高效并发处理共享列表与结果收集的Java教程

    高效并发处理共享列表与结果收集的Java教程高效并发处理共享列表与结果收集的Java教程高效并发处理共享列表与结果收集的Java教程高效并发处理共享列表与结果收集的Java教程

    本文介绍了如何利用Java并发特性,特别是并行流(Parallel Streams),来高效处理共享列表,并将处理结果进行收集。针对耗时操作,通过将列表分割成子列表,并利用并行流并发执行,可以显著提高处理效率。同时,强调了在并发环境下对共享资源进行同步的重要性,并提供了收集处理结果的示例代码。 在处…

    2026年9月25日 • 用户投稿
    000
  • AI Overviews能否用于电商搜索 产品信息摘要在购物场景下的使用体验

    AI Overviews能否用于电商搜索 产品信息摘要在购物场景下的使用体验AI Overviews能否用于电商搜索 产品信息摘要在购物场景下的使用体验AI Overviews能否用于电商搜索 产品信息摘要在购物场景下的使用体验AI Overviews能否用于电商搜索 产品信息摘要在购物场景下的使用体验

    随着人工智能技术的发展,AI Overviews作为一种通过整合信息提供摘要的搜索功能,正逐渐改变用户获取信息的方式。本文将探讨AI Overviews是否以及如何在电商搜索场景下应用,特别关注产品信息摘要对于用户购物体验的影响。我们将讲解其运作原理、潜在优势、面临挑战以及优化体验的过程,帮助理解这…

    2026年9月25日 • 用户投稿
    000
  • AI 图像水印失守!开源工具 5 分钟内抹除所有水印

    AI 图像水印失守!开源工具 5 分钟内抹除所有水印AI 图像水印失守!开源工具 5 分钟内抹除所有水印AI 图像水印失守!开源工具 5 分钟内抹除所有水印AI 图像水印失守!开源工具 5 分钟内抹除所有水印

    ai 图像的水印技术正面临重大挑战! 一种名为 UnMarker 的新型去水印技术横空出世,宣称可在短短5分钟内清除市面上绝大多数 AI 生成图像中的水印。 该技术已成功完全破解谷歌的 HiDDeN 水印系统,对另一款 Google 水印技术 SynthID 的破解率也达到了79%。 更令人震惊的是…

    2026年9月25日 • 用户投稿
    000

发表回复

登录后才能评论
关注微信