
有两个 A、B 两个抽象类分别派生出几个类,我想在一类中加一个指针指向另一类的实例。大致代码如下:
class parentA { public: virtual void func() = 0; parentB* ptrToAnother; // here }; class classA1 : public parentA { public: void func() override; }; class classA2 : public parentA { public: void func( override; }; class parentB { public: virtual void func() = 0; parentA* ptrToAnother; // here }; class classB1 : public parentB { public: void func() override; }; class classB2 : public parentB { public: void func() override; }; classB1 b1; classA1 a1; a1.ptrToAnother = &b1; b1.ptrToAnother = &a1; a1.ptrToAnother->func(); b1.ptrToAnother->func(); 这样就可以通过 ptrToAnother 指针访问另一个类。但是想换成模板实现就爆炸了:
template<typename AnotherClassName> class parentA { public: virtual void func() = 0; AnotherClassName* ptrToAnother; // here }; template<typename AnotherClassName> class classA1 : public parentA<AnotherClassName> { public: void func() override; }; template<typename AnotherClassName> class classA2 : public parentA<AnotherClassName> { public: void func() override; }; template<typename AnotherClassName> class parentB { public: virtual void func() = 0; AnotherClassName* ptrToAnother; // here }; template<typename AnotherClassName> class classB1 : public parentB<AnotherClassName> { public: void func() override; }; template<typename AnotherClassName> class classB2 : public parentB<AnotherClassName> { public: void func() override; }; // 不能编译,缺少模板参数 classA1<classB1> a1; classB1<classA1> b1; a1.ptrToAnother->func(); b1.ptrToAnother->func(); 测试了下这样写能编译,也能正常调用,就是不知道有什么问题
DerivedA<DerivedB<void>> A; DerivedB<DerivedA<void>> B; A.prtToPair = reinterpret_cast<DerivedB<void> *>(&B); B.prtToPair = reinterpret_cast<DerivedA<void> *>(&A); // it works A.ptrToPair->someFunc(); B.ptrToPair->someFunc(); 然后又在StackOverflow上问了下 https://stackoverflow.com/questions/59341379/c-how-to-solve-template-cyclic-dependency-between-derived-classes-when-two-cl
有人提供了一种先拿模板包装的想法:
template<template<typename> typename F, template<typename> typename... Fs> struct Fix { F<Fix<Fs..., F>> unwrapped; }; Fix<DerivedA, DerivedB> dA; Fix<DerivedB, DerivedA> dB; dA.unwrapped.prtToPair = &dB; dB.unwrapped.prtToPair = &dA; dA.unwrapped.prtToPair->unwrapped.func(); dB.unwrapped.prtToPair->unwrapped.func(); 这样的问题就是需要调用两次unwrapped,看起来不习惯
1 gwy15 2019-12-15 13:05:07 +08:00 用模板,ClassA1 的模板参数得是一个具体的类而不是模板类,这里的依赖变成了 type(a1) = classA1<type(b1)> = classA1<classB1<type(a1)>> 所以构成了循环依赖,模板系统里这个方程的解是不存在的,模板没法展开。 如果不关心具体的实现,这样可以通过编译。但是调用的是 derived<int>,不是你想要的那个结果 ```c++ classA1<classB1<int>> a1; classB1<classA1<int>> b1; a1.ptrToAnother = new classB1<int>(); b1.ptrToAnother = new classA1<int>(); a1.ptrToAnother->func(); b1.ptrToAnother->func(); ``` |
2 amai0w0 2019-12-15 13:23:50 +08:00 via Android 在 template 里边的变量必须是特化的,如果里面是另一个另一个 template 类的话什么应该是 template<template<typename> class AntherClassName,typename E>, 然后用 AntherClassName<E>调用。但是这里的 classB1 又是用 classA1 特化,感觉无解了。所以我觉得还是得像前面那样实例化以后再注入。 插眼等一个 dalao |
3 nyanyh OP @amai0w0 #2 @gwy15 #1 刚才发现了一种非常神奇的写法 http://qscribble.blogspot.com/2008/06/circular-template-references-in-c.html ![]() 但是适用于两个固定的类 A 和 B,我这种情况有两堆派生类,如果给 MyCombo 加模板的话就又产生循环依赖的问题了 |
4 secondwtq 2019-12-15 14:06:29 +08:00 试试用 #3 的方法加上 #2 的 HKT template <template<typename> class A, template<typename> class B> struct MyCombo { typedef A<MyCombo<A, B>> a_t; typedef B<MyCombo<A, B>> b_t; }; Aa<MyCombo<Aa, Bb>> a; Bb<MyCombo<Aa, Bb>> b; |
5 nyanyh OP @secondwtq #4 声明变量可以编译,但是给 prtToAnother 赋值就会出错了 a.prtToPair = &b; ^~ error: assigning to 'MyCombo<DerivedA, DerivedB> *' from incompatible type 'DerivedB<MyCombo<DerivedA, DerivedB> > *' |
7 wutiantong 2019-12-16 10:43:02 +08:00 模版对应编译时多态,继承对应运行时多态, 你走的路子还是继承的,非要用模版来掺一脚令人费解啊。 |