可选的参考实现

时间:2011-07-17 19:18:51

标签: c++ c++11

我在这里有一个问题,我不知道如何处理它。首先我是初学者。我有一个类的两个构造函数和两个引用的引用变量但我不能在一个构造函数中使用这两个引用。如果调用cons1(),我需要使用ref1,如果调用cons2,我需要使用ref2。问题在于,当调用cons2时,我应该引用ref1,类似于调用cons1时ref2应该引用的内容。我不知道如何初始化这些引用。它不能为NULL。我不确定是否一个好主意指向一些无效的实现。应该是?这甚至是一种选择吗?如何在c ++中处理这样的问题?

// A.cpp
Class A
A(Object1& a) : ref1(a) {}   - here how should ref2 be handled?
A(Object2& b) : ref2(b) {}- here what should ref1 reference?

// A.h
Object1& ref1
Object2& ref2

我需要在这里使用引用。我知道我们可以使用指针而不是引用,但问题是使用引用特定的。

4 个答案:

答案 0 :(得分:7)

由于ref1和ref2是可选的(不是必需的),所以最好使用指针而不是引用:

class A
{
  public:
    A(Object1& a) : ref1(&a), ref2(NULL) {}
    A(Object2& b) : ref1(NULL),ref2(&b) {}

 Object1 *ref1;
 Object2 *ref2;
};

但稍后你必须检查ref1和ref2是否为NULL。

答案 1 :(得分:2)

警告:以下是愚蠢和做作的。为什么?因为要求使用参考文献也是如此。

class base {
    virtual
    ~base();

    virtual
    void
    stuff_happens() = 0;
};
base::~base() = default;

class case1: public base {
public:
    explicit
    case1(Object1& o)
        : ref(o)
    {}

    void
    stuff_happens()
    {
        // we use ref here
    }

private:
    Object1& ref;
};

class case2: public base {
public:
    explicit
    case2(Object2& o)
        : ref(o)
    {}

    void
    stuff_happens()
    {
        // we use ref here
    }

private:
    Object2& ref;
};

std::unique_ptr<base>
make_base(Object1& o)
{ return std::unique_ptr<base>(new case1(o)); }

std::unique_ptr<base>
make_base(Object2& o)
{ return std::unique_ptr<base>(new case2(o)); }

// ...
{
    auto p = condition ? make_base(ref1) : make_base(ref2);
    p->stuff_happens();
}

答案 2 :(得分:1)

已经给出了正确的答案:切换到指针。在这种情况下,参考文献提供零利益,正如您所看到的那样,有一个巨大的缺点。你的设计开头可疑;让我们不要通过引入额外的不良要求使事情复杂化。

但是,如果你坚持使用引用,唯一可行的解​​决方案是引入某种类型的sentinel值。

struct A {
    A(Object1& o) : obj1(o), obj2(null2) { }
    A(Object2& o) : obj1(null1), obj2(o) { }

    void function() { 
        if(&obj1 == &null1)
            //Object2 constructor
        else
            //Object1 constructor
    }

  private:
    Object1& obj1;
    Object2& obj2;

    static Object1 null1;
    static Object2 null2;
};

//implementation file
Object1 A::null1;
Object2 A::null2;

此方法依赖于Object1Object2两者都具有默认构造函数,或者对于标记具有合理的默认值。 null1null2将在应用程序的整个生命周期中存在,因此如果他们获得任何资源,您将基本上有泄漏。

对于哨兵的无效使用,你也必须更加小心,因为这种访问在[一般情况下]是完全安全的。可以提出一个强有力的论据,即错误会导致可能崩溃的未定义行为,而不是导致错误定义的行为可能会产生意外结果。

答案 3 :(得分:0)

如果需要NULL值,则应从引用切换到指针。有些编译器支持NULL引用,但这样做不好,不可移植,因此应该避免使用。