Как я могу предотвратить этот вид приведения в C ++ - PullRequest
2 голосов
/ 15 апреля 2011

Предположим, есть два класса, таких как

class Locator
{
public:
// this goes to the specified latitide and longitude
bool GoToLocation(long lat, long longtd);
};

class HouseLocator : private Locator
{
public:
// this internally uses GoToLocation() after fetching the location from address map
bool GoToAddress(char *p);
}

Я делаю частное наследование, чтобы заблокировать GoToLocation () на HouseLocator, потому что это не имеет смысла и заставляет людей использовать надлежащий интерфейс.

Теперь мой вопрос, как я могу предотвратить этот тип кастинга?

HouseLocator *phl = new HouseLocator;
Locator *pl = (Locator*)phl;
pl->GoToLocation(10, 10);

Должен ли я просто документировать, чтобы не делать этого, а остальное оставить пользователю, я имею в виду, если он делает неправильный актерский состав, это его проблема?

Ответы [ 6 ]

6 голосов
/ 15 апреля 2011

Используйте композицию вместо наследования:

class Locator
{
public:
    bool GoToLocation(long lat, long longtd);
};

class HouseLocator
{
    Locator locator_;
public:
    // internally uses locator_.GoToLocation()
    bool GoToAddress(char *p);
};

Если это по какой-то причине нецелесообразно, то лучше использовать private наследование, как вы уже знаете, - если пользователь разыгрывает HouseLocator*на Locator* они вызывают неопределенное поведение, и это их проблема, а не ваша.

2 голосов
/ 15 апреля 2011

Если вы можете изменить базовый класс, вы можете сделать функцию protected вместо public.

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

1 голос
/ 15 апреля 2011

Это выглядит так, как будто HouseLocator, вероятно, не должно происходить от Locator.Из ограниченного контекста вы, вероятно, захотите что-то, что использует локатор (т. Е. Он составлен как закрытая переменная-член).

Частное наследование почти исключительно используется как устройство композиции, когда вы не можетесочинять напрямую (потому что вам также нужно специализировать класс).

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

1 голос
/ 15 апреля 2011

Вы не можете.Приведение C включает функцию reinterpret_cast, и вы не можете предотвратить reinterpret_casting между любыми двумя типами указателей данных.

Обратите внимание, что это приведение не будет выполнять корректировки, необходимые в некоторых случаях множественного наследования, и, следовательно, может не достичь егоожидаемый результат.(static_cast выполнит настройки, но проверит доступность).

0 голосов
/ 15 апреля 2011

Вы также можете конвертировать оператора

operator Locator() const;

, что вызывает исключение в классе HouseLocator. Но это не помешает конвертации с помощью reinterpret_cast <>. Ничто не может этому помешать.

0 голосов
/ 15 апреля 2011

Не стоит пытаться предотвратить это ИМХО.Пользователь может в любом случае сделать Locator* p = new Locator(); p->GoToLocation(10,10);

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