c++ - C ++:当两个类包含指向另一个类的指针时,如何解决派生类之间的模板循环依赖?
问题描述
我有一个父类和一些从它派生的类。我想“配对”两个派生类,其中 eac 有一个指向另一个的指针。
代码示例:
template<typename DerivedClassName>
class Parent {
// some stuff
DerivedClassName* prtToPair;
};
template<typename DerivedClassName>
class DerivedA : public Parent<DerivedClassName> {
};
template<typename DerivedClassName>
class DerivedB : public Parent<DerivedClassName> {
};
// compile fails
DerivedA<DerivedB> dA;
DerivedB<DerivedA> dB;
dA.prtToPair = &dB;
dB.prtToPair = &dA;
我知道我可以用虚函数做到这一点,但我试图找到一种使用模板的方法。
我从http://qscribble.blogspot.com/2008/06/circular-template-references-in-c.html找到了一个解决方案:
#include <stdio.h>
template<class Combo> struct A
{
typedef typename Combo::b_t B;
B* b;
};
template<class Combo> struct B
{
typedef typename Combo::a_t A;
A* a;
};
struct MyCombo {
typedef A<MyCombo> a_t;
typedef B<MyCombo> b_t;
};
int main(int argc, char* argv[])
{
A<MyCombo> a;
B<MyCombo> b;
a.b = &b;
b.a = &a;
return 0;
}
但它只适用于两个固定类 A 和 B。考虑到我有很多派生类,我想“配对”其中的任何两个,我该如何解决这个问题?
更新 1. 修复第一个代码块中的拼写错误 更新 2. 我尝试了以下代码
template<typename DerivedClassName>
class Parent {
// some stuff
public:
DerivedClassName *prtToPair;
};
template<typename DerivedClassName>
class DerivedA : public Parent<DerivedClassName> {
public:
void func() {
std::cout << "A" << std::endl;
}
};
template<typename DerivedClassName>
class DerivedB : public Parent<DerivedClassName> {
public:
void func() {
std::cout << "B" << std::endl;
}
};
int main() {
DerivedA<DerivedB<void>> A;
DerivedB<DerivedA<void>> B;
A.prtToPair = reinterpret_cast<DerivedB<void> *>(&B);
B.prtToPair = reinterpret_cast<DerivedA<void> *>(&A);
A.prtToPair->func();
B.prtToPair->func();
return 0;
}
它编译并打印B A
。但是这段代码正确吗?它有任何副作用吗?
解决方案
DerivedB
不是一个类;这是一个模板。你不能只拥有一个DerivedA<DerivedB>
,因为那没有意义。里面是什么样的 ?如果你这样想,你就会看到问题:你的两个变量的类型是无限的:一个是,另一个是。你不能有一个无限的类型。您必须在某处使用包装类来打破循环。这种情况的通用包装器类型是DerivedB
DerivedA
DerivedA<DerivedB<DerivedA<DerivedB<...>>>>
DerivedB<DerivedA<DerivedB<DerivedA<...>>>>
template<template<typename> typename F, template<typename> typename... Fs>
struct Fix {
F<Fix<Fs..., F>> unwrapped;
};
Fix<F1, F2, ..., Fn>
代表F1<F2<...<Fn<F1<F2<...>>>>...>>
。你可以这样得到你的两个对象:
Fix<DerivedA, DerivedB> dA;
Fix<DerivedB, DerivedA> dB;
dA.unwrapped.prtToPair = &dB;
dB.unwrapped.prtToPair = &dA;
推荐阅读
- sql - 根据地址相似性查找示例
- paypal - Paypal 计费计划和计费协议
- jmeter - 我如何在 JMeter5.0 中连接工作台 Sql
- npm-install - npm install -g 工作正常,npm install 抛出错误“npm ERR!404 Not Found - GET http://registry.npmjs.org/storybook__addon-knobs - Not found”
- python - 当 csrf_enabled 为 True 时,Flask-WTF 抛出错误(设置了 SECRET_KEY)
- eclipse - 插件中没有依赖注入和缺少 EclispeContext
- reactjs - 在基于函数的组件中使用构造器项
- python - 为从同一数据框中提取的变量添加新记录到数据框中
- mysql - 排序字段的数据重复时MySql如何对数据进行排序?
- node.js - 我无法通过 npm run 命令运行脚本。我的脚本名称是“开始”。每当我通过此命令运行此脚本时,我都会收到错误