как реализовать приведение к частному базовому классу в C ++ - PullRequest
1 голос
/ 17 сентября 2010

Как реализовать приведение к закрытому базовому классу в C ++? Я не хочу использовать такие хаки, как добавление друга и т. Д. Определение оператора публичного кастинга не работает.

РЕДАКТИРОВАТЬ:

Например, у меня есть:

class A {
//base class
}

class AX : private A {
//a child
}

class AY : private A {
//another specialized child
}

class B {
//base class
void do (A a) {//do
    }
}

class BX : private B {
//a child
void do (AX a) {
     B::do( static_cast <A> (a) );
    }
}

class BY : private B {
//another specialized child
void do (AY a) {
    B::do( static_cast <A> (a) );
    }
}

EDIT2

Почему я это делаю?

Предположим, мне нужно определить какое-то свойство, которое является достаточно тяжелым и может иметь несколько похожих типов (например, VelocityX VelocityY и т. Д.). Тогда я хочу иметь возможность иметь классы, которые могут иметь любой набор этих свойств. Если я захочу обработать эти свойства, очевидно, что я бы предпочел привести их к базовому типу, чем добавлять реализацию для каждого варианта. Я не использую публичное наследование, потому что лучше явно приводить при необходимости, чем неявно видеть частный интерфейс. Не реальная проблема, но я хотел бы иметь решение :)

Ответы [ 3 ]

6 голосов
/ 18 сентября 2010

Если определение общедоступного оператора приведения не работает, вы можете попробовать использовать обычную функцию:

class D: private B {
    public:
        B& asB() { return static_cast<B&>(*this); }
};
...
D d;
d.asB().methodInB();
...

В любом случае, какой смысл? Если D является производным от B, то вы не должны использовать D как B извне.

4 голосов
/ 18 сентября 2010

Вы можете просто использовать кастинг в стиле C.Нет необходимости в каких-либо «взломах» или «реализациях».Включение в явную функцию служит тому, что "C-Style бросает плохо" людей

template<typename Targ, typename Src>
typename boost::enable_if<boost::is_base_of<Targ, Src>, Targ>::type &
private_cast(Src &src) { return (Targ&)src; }

Чтобы иметь безопасный бросок, вам нужно убедиться, что Targ на самом деле является частной или общедоступной базой.Это сделано boost::is_base_of.


Конечно, вы должны предпочесть функции-члены в соответствующем производном классе, которые возвращают базовый указатель, вместо того, чтобы выполнять такое приведение. .


Определение оператора публичного приведения не работает.

Это не имеет смысла для меня ... Зачем вообще делать личный базовый класс?Просто сделайте это публичным.Причина, по которой ваши функции преобразования не работают, заключается в том, что Стандарт требует, чтобы неявные преобразования никогда не рассматривали функции преобразования в базовый класс, сам класс или void.

0 голосов
/ 23 апреля 2015

У меня есть вариант использования для этого; Я наследую от большого и изменчивого базового класса, который постоянно добавляет функции, и почти никогда функция базового класса не будет работать правильно в моем подклассе, поэтому я наследую в частном порядке.

Я думаю, что проще всего сделать функцию, которая возвращает базовый класс. Ниже я перечисляю полностью исправленную программу; Пожалуйста, попробуйте скомпилировать свой код перед отправкой вопроса, поскольку использование идентификаторов, таких как "do", в качестве имен функций, вероятно, сделает каждый компилятор несчастным .. :-(: - (

class A {
  //base class                                                                                                                                                          
};

class AX : private A {
  //a child                                                                                                                                                             
 public:
  A *ToA() { return this; }
};

class AY : private A {
  //another specialized child                                                                                                                                           
 public:
  A *ToA() { return this; }
};

class B {
  //base class                                                                                                                                                          
 protected:
  void do_it (A a) {};
};

class BX : private B {
  //a child                                                                                                                                                             
  void do_it (AX a) {
    B::do_it( *a.ToA() );
  }
};

class BY : private B {
  //another specialized child                                                                                                                                           
  void do_it (AX a) {
    B::do_it( *a.ToA() );
  }
};
...