如何创建共享相同成员的Mixin类?解决多继承段错误问题
如何创建可共享相同成员的Mixin类?
我明知这可能是不佳的设计选择,但已是最后方案。以下是示例代码(注意其中的指针并未共享):
struct Full{ int a = 213; int b = 500; int c = 400; }; struct ProxyA{ std::shared_ptr<Full> full; void say_a(){ std::cout << full->a; } }; struct ProxyB{ std::shared_ptr<Full> full; void say_b(){ std::cout << full->b; } }; struct FullProxy: public ProxyA, public ProxyB{ std::shared_ptr<Full> full; FullProxy(std::shared_ptr<Full> full_): full{full_}{}; void say_c(){ std::cout << full->c << "\n"; } }; int main() { FullProxy foo(std::make_shared<Full>()); foo.say_a(); foo.say_b(); foo.say_c(); }
运行输出:
ASM generation compiler returned: 0 Execution build compiler returned: 0 Program returned: 139 Program terminated with signal: SIGSEGV
注:我无法使用模板,因为这些类需要包含Q_PROPERTY,而Qt不支持模板。
我意识到Qt不支持多继承,因此该方案无法在Qt中使用。
问题根源
代码崩溃是因为ProxyA和ProxyB中的full指针从未被初始化——FullProxy的构造函数只初始化了自身的full成员,基类的full仍为空指针,调用say_a()/say_b()时访问空指针触发段错误。同时当前设计存在冗余:三个shared_ptr指向同一个对象,完全没必要。
可行解决方案
方案1:初始化基类成员(简单但冗余)
直接在FullProxy的构造函数中显式初始化基类的full指针:
struct FullProxy: public ProxyA, public ProxyB{ std::shared_ptr<Full> full; FullProxy(std::shared_ptr<Full> full_): ProxyA{full_}, ProxyB{full_}, full{full_}{}; void say_c(){ std::cout << full->c << "\n"; } };
这种方式能解决崩溃问题,但每个基类和派生类都持有一份shared_ptr,存在冗余。
方案2:虚拟继承共享成员(消除冗余)
定义一个持有共享成员的基类,让所有Mixin类虚拟继承它,确保整个继承体系中只有一份共享成员实例:
struct FullHolder { std::shared_ptr<Full> full; FullHolder(std::shared_ptr<Full> full_) : full(std::move(full_)) {} std::shared_ptr<Full> get_full() const { return full; } }; struct ProxyA: virtual public FullHolder{ using FullHolder::FullHolder; // 继承构造函数 void say_a(){ std::cout << get_full()->a; } }; struct ProxyB: virtual public FullHolder{ using FullHolder::FullHolder; void say_b(){ std::cout << get_full()->b; } }; struct FullProxy: public ProxyA, public ProxyB{ FullProxy(std::shared_ptr<Full> full_): FullHolder(std::move(full_)), ProxyA(full_), ProxyB(full_){} void say_c(){ std::cout << get_full()->c << "\n"; } };
所有Mixin类都通过FullHolder获取共享的full指针,彻底避免了冗余。
方案3:组合替代继承(适配Qt限制)
由于Qt不支持多继承,改用组合方式,把Mixin类作为成员变量,在FullProxy中转发调用:
struct FullProxy{ std::shared_ptr<Full> full; ProxyA proxy_a; ProxyB proxy_b; FullProxy(std::shared_ptr<Full> full_): full(std::move(full_)), proxy_a{full}, proxy_b{full}{} // 转发调用 void say_a() { proxy_a.say_a(); } void say_b() { proxy_b.say_b(); } void say_c(){ std::cout << full->c << "\n"; } };
这种方式完全避开多继承,符合Qt的要求,同时保证所有组件共享同一个full指针。
内容的提问来源于stack exchange,提问作者user16776498
相关产品推荐
相关产品推荐

