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

时间:2009-12-14 00:02:39

标签: 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;
};

Visual C ++ 2008告诉我:

error C2514: 'B' : class has no constructors

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

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

1 个答案:

答案 0 :(得分:7)

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

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

class B...

void A::func() { func(B()); }
void A::func(const B&) { }

更新

  

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

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

const B& foo = a.func();
foo.bar();

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

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

a.func(B()).bar();

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

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

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

我无法分辨您尝试使用此功能的方法,但您可能需要查看一些Design Patterns以查看是否已建立最佳实践。你可能会发现这个小问题是不幸选择阶级结构或遏制的症状。