我经常在方法中创建本地帮助器类,只要这样的类在本地有用但在方法之外无关紧要。我刚刚遇到一个案例,我想要两个相互依赖的本地类。
我们的想法是拥有以下模式:
void SomeClass::someMethod()
{
struct A
{
B * b;
void foo() { if(b) b->bar(); };
};
struct B
{
A * a;
void bar() { if(a) a->foo(); }
};
}
但由于A
需要B
,因此无法编译。前向声明B
有帮助,以便行B * b;
编译,但方法A::foo()
仍然需要B
的完整声明,并且编译器会抱怨。
我看到两个解决方法:
在SomeClass::someMethod()
之前在SomeClass.cpp中声明和定义类。我觉得这不优雅,因为不仅SomeClass::someMethod()
不是本地的课程,而且SomeClass
都不是本地课程。
声明SomeClass.h中的类嵌套在SomeClass
中,并在SomeClass.cpp中定义它们。我不喜欢这个解决方案,因为不仅类不是SomeClass::someMethod()
的本地类,而且除了语言的限制外,它确实没有任何理由污染SomeClass.h。
因此有两个问题:是否可以让SomeClass::someMethod()
的本地类成为可能?如果没有,你看到更优雅的解决方法吗?
答案 0 :(得分:1)
实施虚拟A,供B使用,然后实现真正的A.
struct virtA
{
virtual void foo() = 0 ;
} ;
struct B
{
virtA * a ;
void bar() { if ( a) { a->foo() ; } }
} ;
struct A : public virtA
{
B * b ;
void bar() { if ( b) { b-> bar() ; } }
} ;
答案 1 :(得分:0)
由于答案似乎是:“不可能拥有干净的相互依赖的本地类”,事实证明我最喜欢的解决方法是将逻辑移到结构本身之外。正如remyabel在问题的评论中所建议的,它可以通过创建第三个类来完成,但我最喜欢的方法是创建相互递归的lambda函数,因为它可以捕获变量(因此在我的实际情况下使我的生活更轻松)用法)。所以它看起来像:
#include <functional>
#include <iostream>
int main()
{
struct B;
struct A { B * b; };
struct B { A * a; };
std::function< void(A *) > foo;
std::function< void(B *) > bar;
foo = [&] (A * a)
{
std::cout << "calling foo" << std::endl;
if(a->b) { bar(a->b); }
};
bar = [&] (B * b)
{
std::cout << "calling bar" << std::endl;
if(b->a) { foo(b->a); }
};
A a = {0};
B b = {&a};
foo(&a);
bar(&b);
return 0;
}
编译并打印:
calling foo
calling bar
calling foo
请注意,必须手动指定lambdas的类型,因为类型推断不适用于递归lambda。