необязательная эталонная реализация - PullRequest
2 голосов
/ 17 июля 2011

У меня проблема здесь, когда я не уверен, как с этим справиться. Во-первых, я новичок. У меня есть два конструктора для класса и объявлены две ссылочные переменные, но я не могу использовать обе ссылки в одном конструкторе. Если вызывается cons1 (), мне нужно использовать ref1, а если вызывается cons2, мне нужно использовать ref2. Проблема в том, на что я должен ссылаться на ref1, когда вызывается cons2, и аналогично тому, на что должен ссылаться ref2, когда вызывается cons1. Я не уверен, как инициализировать эти ссылки. Это не может быть 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 ]

7 голосов
/ 17 июля 2011

Поскольку 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.

2 голосов
/ 18 июля 2011

ПРЕДУПРЕЖДЕНИЕ: следующее глупо и надумано. Зачем? Потому что таково требование использовать ссылки.

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();
}
1 голос
/ 18 июля 2011

Правильный ответ уже дан: переключайтесь на указатели. Ссылки в этом случае дают нулевую выгоду, и, как вы видели, имеют огромный недостаток. Ваш дизайн сомнителен для начала; давайте не будем усложнять ситуацию, вводя дополнительные плохие требования.

Однако, если вы настаиваете на использовании ссылок, единственно возможное решение - это ввести какое-либо значение дозорного.

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;

Этот метод зависит от того, имеют ли Object1 и Object2 конструкторы по умолчанию или иное разумное значение по умолчанию для часовых. null1 и null2 будут существовать в течение всего срока службы приложения, поэтому, если они получат какие-либо ресурсы, у вас по существу будет утечка.

Вы также должны быть намного осторожнее с недопустимым использованием часовых, поскольку такой доступ [в общем случае] совершенно безопасен. Можно привести веские аргументы в пользу того, что ошибкам лучше привести к неопределенному поведению, которое может привести к сбою, чем к четко определенному поведению, которое может просто привести к неожиданным результатам.

0 голосов
/ 17 июля 2011

Если вам нужны значения NULL, вам следует перейти от ссылки к указателю.Некоторые компиляторы поддерживают ссылки NULL, но это плохой стиль и не переносимый, поэтому его следует избегать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...