声明没有指针的默认参数循环引用?

Ash*_*ain 0 c++ header definition circular-reference

有没有办法在没有间接的头文件中声明这些类?

// Forwards declaration of B
class B;

class A
{
public:
    // Default parameter referring to B.  May return its parameter
    const B& func(const B& b = B());
};

class B
{
public:
    // B ctors
    B() {}
    B(const B&) {}

    // B has A as a member
    A a;
};
Run Code Online (Sandbox Code Playgroud)

Visual C++ 2008告诉我这个:

error C2514: 'B' : class has no constructors
Run Code Online (Sandbox Code Playgroud)

并指出B的前向声明("B类;"),显然不能在下面看到B的构造函数.A不能跟随B,因为B包含A作为成员.

如果必须使用间接,那么最好的方法是什么?也许在C++ 0x B中A可能是unique_ptr成员?或者也许有一个提升类纯粹是为了回避这个问题?

Tim*_*ter 7

而不是默认参数声明两个重载,一个采用B引用而另一个不采用参数.在不带参数的那个中,调用另一个B(),这将起作用,因为该方法可以在定义之后B定义.

...
    void func();
    void func(const B& b);
};

class B...

void A::func() { func(B()); }
void A::func(const B&) { }
Run Code Online (Sandbox Code Playgroud)

更新:

func()返回一个const B&...

这可能不是一个好主意.有了这个定义,就像:

const B& foo = a.func();
foo.bar();
Run Code Online (Sandbox Code Playgroud)

会导致可怕的"未定义行为"(即崩溃),因为B一旦第一个语句完成,你的引用就会被销毁.通过引用返回类成员以外的东西通常是一个坏主意.

如果你真的想这样做,那么我认为你不得不强迫调用者显式传入B(),那就是没有默认参数.

a.func(B()).bar();
Run Code Online (Sandbox Code Playgroud)

(这是避免使用此类函数的未定义行为的唯一方法.)

当然你可以只返回副本而不是引用,但我认为你有理由不这样做.

根据您正在做的事情,您可以使用智能指针shared_ptr而不是引用来设置更好的语义,以便您可以有效地忽略对象的生命周期.然而,你必须开始小心参考周期.

我不知道你想要使用它的是什么,但你可能想看一些设计模式,看看是否有一个已建立的最佳实践.你可能会发现这个小问题是不幸选择阶级结构或遏制的症状.