C++匿名结构体实例地址异常:子类调用父类时实例复用问题
C++子类调用父类时共享全局匿名结构体实例的问题:原因与解决方法
问题原因
- 匿名结构体的链接特性:你在
shope.h中定义的匿名结构体实例unnameStruct,由于匿名类型无外部链接性,每个包含该头文件的编译单元(.cpp文件)都会独立生成一个全局的unnameStruct实例。 - 父类方法的编译单元归属:
ChinaBaseShop::income的实现位于shope.cpp中,因此该方法内访问的unnameStruct是shope.cpp编译单元专属的全局实例,地址固定。无论BeijingShop还是TianjinShop调用父类的income方法,最终执行的都是shope.cpp中的代码,必然访问同一个实例,所以地址完全相同。 - 子类方法中的
unnameStruct则属于各自的编译单元(beijing_shope.cpp、tianjin_shope.cpp),因此地址与父类中的实例不同,但父类的实例始终唯一。
解决方法
方案1:将结构体改为父类的非静态成员(实例级独立)
让每个门店实例(包括子类实例)拥有自己的结构体实例,彻底避免全局共享:
修改shope.h:
#pragma once #include <iostream> #include <string> using namespace std; struct ChinaBaseShop { // 定义命名结构体作为内部类型 struct ShopFlag { string flag = "init value"; void print(string newFlag) { cout << "ShopFlag's address:" << this << '\t'; cout << "flag's address:" << &flag << '\t'; cout << "rawFlag:" << flag << '\t'; flag = newFlag; cout << "newFlag:" << flag << '\t' << endl; } }; static double turnover; /* 流水收入 */ ShopFlag shopFlag; // 每个实例独立拥有的结构体 virtual void income(double money); };
修改shope.cpp的income方法:
#include "shope.h" double ChinaBaseShop::turnover = 0.0; void ChinaBaseShop::income(double money) { cout << "ChinaBaseShop's Address : " << this << endl; shopFlag.print("Headquarters in China"); // 访问当前实例的结构体 turnover += money; }
修改子类BeijingShop::income(TianjinShop同理):
void BeijingShop::income(double money) { cout << "-BeiJing–" << endl; cout << "BeijingShop's Address:" << this << endl; shopFlag.print("BeiJing shope"); // 访问当前实例的结构体 ChinaBaseShop::income(money); if(money > 100) { turnover -= 10.0; } }
此方案下,每个门店实例的结构体地址与实例绑定,父类方法访问的是当前调用实例的结构体,完全符合你“不同子类上下文使用不同结构体实例”的需求。
方案2:静态成员(子类级共享)
若希望同一子类的所有实例共享一个结构体,可将结构体定义为子类的静态成员:
以BeijingShop为例,修改beijing_shope.h:
#pragma once #include "shope.h" struct BeijingShop : ChinaBaseShop { static struct ShopFlag { string flag = "init value"; void print(string newFlag) { // 实现同方案1的ShopFlag } } shopFlag; virtual void income(double money) override; };
修改beijing_shope.cpp:
#include "beijing_shope.h" // 初始化静态成员 decltype(BeijingShop::shopFlag) BeijingShop::shopFlag; void BeijingShop::income(double money) { cout << "-BeiJing–" << endl; cout << "BeijingShop's Address:" << this << endl; shopFlag.print("BeiJing shope"); ChinaBaseShop::income(money); if(money > 100) { turnover -= 10.0; } }
同理修改TianjinShop,即可实现同一子类的所有实例共享一个结构体,不同子类的结构体相互独立。
内容的提问来源于stack exchange,提问作者Tom
相关产品推荐
相关产品推荐

