【问题标题】:C++ circular dependencies with nested class具有嵌套类的 C++ 循环依赖项
【发布时间】:2020-06-24 06:38:33
【问题描述】:

我正在尝试生成我用 IDA 反汇编的类的头文件。但是,由于循环依赖,我得到了编译错误。对于常规类,我通过在一个单独的文件中声明它们来解决它,我首先将它们包含在内。问题是我不能在没有定义外部类的情况下声明内部类,这是问题所在。

一个示例类结构:

A类:

#include "B.h"

class A {

public:
    class Nested {
    public:
        void foo(B::Nested &foo);
    };
};

B类:

#include "A.h"

class B {

public:
    class Nested {
    public:
        void foo(A::Nested &foo);
    };
};

【问题讨论】:

  • 不,因为正如我所说,如果不定义外部类,就不可能声明嵌套类。并且外部类的早期定义导致另一个循环依赖。
  • 您必须将它们设为单独的类。见stackoverflow.com/questions/951234/…。如有必要,让他们成为他们“以前的”父类的朋友。
  • 你必须对代码进行更多的模块化。它会产生问题
  • 有什么理由需要嵌套这些类吗?

标签: c++ inner-classes circular-dependency


【解决方案1】:

当编译器读取您的文件时,它需要声明的实体。

您可以转发声明该类,但您会缺少嵌套参数类型。

你可以做的是有一个打破循环依赖并继承到你的嵌套类的第三个类:

class NestedBase {
};

现在在你的 A 嵌套类中使用这个基础:

#include "NestedBase.h"

class A {

public:
    class Nested : public NestedBase {
    public:
        void foo(NestedBase &foo);
    };
};

在您的 B 嵌套类中也是如此:

#include "NestedBase.h"

class B {

public:
    class Nested : public NestedBase {
    public:
        void foo(NestedBase &foo);
    };
};

现在在您的方法实现中使用dynamic_cast,您可以将它们转换为您想要的类型并访问您在嵌套类中声明的任何内容。

#include "A.h"
#include "B.h"

B::Nested::foo(NestedBase &foo)
{
    auto &fooA = dynamic_cast<A::Nested&>(foo);
    ...
}

【讨论】:

    【解决方案2】:

    使用模板。

        class A {
    public:
        class Nested {
        public: 
            template<class B>
            void foo(typename B:: Nested &fo);
        };
    };
    
    class B {
    public:
        class Nested {
        public: 
            template<class A>
            void foo(typename A:: Nested &fo);
        };
    };
    
    template<>
    void A::Nested::foo<B>(B::Nested & fo){
    }
    
    template<>
    void B::Nested::foo<A>(A::Nested & fo){
    }
    

    例如(此处模板已上移,因此不必为每个函数调用指定类型。)

    #include <iostream>
    
    class A {
    public:
       template <class B>
       class Nested {
        public: 
            std::string name() const { return "a"; }
    
            void foo(typename B:: template Nested<A> &fo);
        };
    };
    
    class B {
    public:
        template <class A>
        class Nested  {
        public: 
            std::string name() const { return "b"; }
    
            void foo(typename A:: template Nested<B> &fo);
        };
    };
    
    template<>
    void A::Nested<B>::foo(B::Nested<A> & fo){
        std::cout << "A::Nested " << fo.name() << '\n';
    }
    
    template<>
    void B::Nested<A>::foo(A::Nested<B> & fo){
        std::cout << "B::Nested " << fo.name() << '\n';
    }
    
    int main()
        {
            A::Nested<B> a;
            B::Nested<A> b;
            a.foo(b);
            b.foo(a);
        }
    

    【讨论】:

    • 如果你这样做,至少添加一个模板保护,例如:template&lt;typename A_ = A, typename = std::enable_if&lt;std::is_same&lt;A_, A&gt;::value&gt;&gt;
    【解决方案3】:

    您可以在AB中转发声明Nesteds,然后再定义它们。

    啊。

    class A {
    public:
        class Nested;
    };
    

    B.h

    class B {
    public:
        class Nested;
    };
    

    嵌套.h

    #include "A.h"
    #include "B.h"
    
    class A::Nested {
    public:
        void foo(B::Nested &foo);
    };
    
    class B::Nested {
    public:
        void foo(A::Nested &foo);
    };
    

    【讨论】:

      猜你喜欢
      • 2019-10-25
      • 1970-01-01
      • 1970-01-01
      • 2017-06-12
      • 1970-01-01
      • 1970-01-01
      • 2015-03-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多