2009-04-07 3 views
6

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

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

РЕДАКТИРОВАТЬ: Придется изменить это дальше ... Я уверен, что класс не будет изменен, так что все в порядке ... моя единственная забота заключается в том, если человек, который закодировал этот класс, узнает этого, он не может спуститься и с ним :(

+0

Что конкретно вы пытаетесь сделать, выполнив это? –

ответ

6

«Никогда не говори никогда». Я уверен, что где-то во вселенной есть ситуация, которая заставит вас это сделать ...

Но я, конечно, съежился бы, если бы мне пришлось это сделать. Вам действительно нужно получить много мнений о вашей ситуации, прежде чем нажать на курок. Можете ли вы описать свою конкретную ситуацию, и, возможно, мы могли бы понять, имеет ли смысл или какие альтернативы могут существовать?

В ответ на комментарий/вопрос - Определить «разрешения» - институциональное разрешение? Это звучит не как проблема программирования, а что-то, чтобы поговорить с тем, кто утверждает указанное разрешение. Может быть, это скорее политическая проблема, чем техническая? Опять же, я думаю, что нам нужно больше деталей, даже если бы это было связано с политикой ситуации. Тем не менее, это может быть или не быть признано вне сферы действия для веб-сайта.

+0

Я думаю, что я упомянул об этом в вопросе .. У меня нет доступа к этому определению, но мне нужен член, определенный в этом классе, для вычисления некоторого значения. – Shree

+2

выбросить этот класс и использовать класс, обеспечивающий доступ к члену. –

+0

Это был бы другой класс. У него нет доступа к желаемому участнику. – southerton

26

Я не уверен, что «этика» действительно приходят в него бюсты щеколда капсулирования хотя

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

+0

Это правда, но если у вас нет другого способа сделать это, возможно, придется отпустить определенные понятия? – Shree

+0

Инкапсуляция на самом деле не существует для защиты от злоупотреблений. Иногда это единственный способ пойти :-( –

+0

Если это класс людей, которых вы нарушаете, тогда есть основные этические проблемы :-) – veefu

3

Это этично, но обычно это грязный код, соседний с неопределенным поведением и неспортивностью. Сделайте это, только если вам абсолютно необходимо.

+0

Люди очень либеральны (читайте «ленивые»), когда определяете, где находится линия «абсолютно необходима». –

+0

Правда, и это приводит к серии простых, но интересных вопросов интервью, которые помогают в найме только людей с необходимой степенью ленивости. – sharptooth

+0

Да. Для интервьюера и кандидата. –

9

Нет. Что вы делаете, это Pure Evil.

+0

Эй, вы украли мои невидимые теги от http://stackoverflow.com/questions/722350/should-your-opensource-project-attempt-to-mimic-commercial-products. – chaos

+0

Я думал, что невидимые теги были с открытым исходным кодом! –

5

Если вы чувствуете желание сделать это, забыть отливку - просто изменить объявление класса в заголовочном файле:

class A { 
    private: 
    int x; 
}; 

изменения, что:

class A { 
    public: 
    int x; 
}; 

, и вы хорошо идти , Ну, может быть, «хороший» - не совсем правильное слово.

+0

Почему бы не упомянуть, что он нарушает ODR. он также переходит от не-POD к POD. Я представляю себе, что лучше что-то ломается. как он есть, можно было бы прочитать свой ответ как «вы можете просто сделать ... это сработает» –

+0

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

+0

Он только разбивает ODR, если определение A находится в библиотеке. И я не был абсолютно серьезным ... –

2

Ах, абстракция - вы не можете жить без него, и все же это так больно, чтобы иметь дело с иногда :)

Во всяком случае, этика в сторону, что, если «владелец» класса решает изменить внутренний реализации или просто отменяет порядок частных членов данных?

+0

В общем, только больно иметь дело, если вы его привинтите. –

+0

@John так верно! +1 –

1

Простой ответ: Нет

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

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

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

+0

Принято ... вот почему я случайно задал этот вопрос ... но есть ли другой способ доступа к членам? По крайней мере, я не могу придумать ... – Shree

+0

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

27

Давайте не будем рассматривать этику на мгновение. Давайте рассмотрим стандарт.

То, что вы предлагаете сделать, нестандартно. См. Раздел 9.2, раздел 12 стандарта. «Порядок распределения нестатических членов, разделенных спецификатором доступа, не указан». Поэтому, если у вас есть класс с частными членами и структура без частных членов, стандарт не гарантирует, что члены будут в одном порядке.

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

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

Herb Sutter написал a Guru of the Week столбец по этому вопросу.

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

+0

В избранное ... – Shree

+0

Действительно хорошая ссылка на GoTW. Я мог бы снова подняться, если бы мог. –

+0

Огромное спасибо ... Я как раз собирался выкопать свою копию стандарта и проверить условие распределения для гарантий. Очень приятная детективная работа. –

6

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

Если в некоторых случаях вам просто нужно сделать взломать.

В исходном файле, с которого необходимо получить доступ к закрытому члену данных вы можете поместить в этом качестве первой линии:

#define private public 
#define protected public 

и доступ все, что вы хотите.

+0

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

1

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

Частные члены только что. Он может и, скорее всего, однажды изменит этого члена. Когда это произойдет, вы можете даже не заметить, что там, скорее всего, будет память, а не тот, кого вы ожидали. Черт, почти любая невозможная вещь, которую вы можете себе представить, может начать происходить, когда ваш код запущен. Как кто-нибудь когда-нибудь сможет отладить это?

12

Я только что добавил entry to my blog, который показывает, как это можно сделать совершенно соответствующим образом. Вот пример того, как вы используете его для следующего класса

struct A { 
private: 
    int member; 
}; 

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

struct Amem { typedef int type; }; 
template class rob<Amem, &A::member>; 

int main() { 
    A a; 
    a.*result<Amem>::ptr = 42; // Doh! 
} 

Но на самом деле, это не показывает, что с правилами доступа ++ 's не являются надежными. Правила языка предназначены для защиты от случайных ошибок - если вы пытаетесь ограбить данные объекта, язык by-design не займет много времени, чтобы предотвратить вас.


выше способ доступа частных и защищенных членов в соответствующем пути. Это один из способов доступа к защищенным членам в стандартном соответствии. Основная идея состоит в том, чтобы использовать указатель участника

std::deque<int> &getAdapted(std::stack<int> &s) { 
    struct voyeur : stack<int> 
    { using stack<int>::c; }; 
    return s.*(&voyeur::c); 
} 

int main() { 
    std::stack<int> s; 
    std::deque<int> &adapted = getAdapted(s); 
    output(adapted); // print the stack... 
} 

Не применяется литье или наложение типа. Он принимает указатель на защищенный член std::stack<int> через класс, полученный из него, где это имя участника является общедоступным, поэтому компилятор разрешает это. Затем он использует его на объекте std::stack<int>, что тоже допускается.

0

Я предполагаю, что этот класс является частью проекта, над которым вы работаете.

Существует одна этическая проблема: Если в вашей компании вы видите право собственности на код как крестца. В худшем случае вам запрещено изменять код, который не принадлежит вам. Да. Вы можете повредить чувства человека, поддерживающего этот класс. Или рассердить его, если его зарплата связана с его кодом. , так что лучше всего попросить его о помощи, и несколько предложений, например. добавьте функцию getter или измените конфиденциальность для публики - все зависит от вашей интуиции использования этого нового кода.

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

Смежные вопросы