Расширяете существующий класс как пространство имен (C ++)? - PullRequest
4 голосов
/ 23 октября 2008

Я пишу от второго лица только потому, что это легко для вас.

Вы работаете с игровым движком и действительно хотите, чтобы у определенного класса движков был новый метод, который делает 'bla'. Но вы не хотели бы распространять свой код «игры» в код «движка».

Таким образом, вы можете извлечь из него новый класс одним новым методом и поместить этот код в исходный каталог «игры», но, возможно, есть другой вариант?

Так что это, вероятно, абсолютно недопустимо в языке C ++, но вы сначала подумали: «Возможно, я могу добавить новый метод к существующему классу через мой собственный заголовок, который включает в себя заголовок« parent »и некоторый специальный синтаксис. возможно при работе с пространством имен, например ... "

Предполагая, что вы не можете объявить методы класса в нескольких заголовках (и вы чертовски уверены, что не можете), каковы другие варианты, которые поддерживают четкое разделение между 'middleware / engine / library' и 'application ', вам интересно?

Ответы [ 8 ]

8 голосов
/ 23 октября 2008

Мой единственный вопрос к вам: «Должна ли ваша добавленная функциональность быть функцией-членом или она может быть бесплатной?» Если то, что вы хотите сделать, может быть решено с использованием существующего интерфейса класса, тогда единственное отличие - это синтаксис, и вы должны использовать свободную функцию (если вы думаете, что это «некрасиво», тогда ... смиритесь с этим и продолжайте, C ++ не был разработан для мартышек).

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

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

Для более подробного обсуждения (и деконструкции std::string '), ознакомьтесь с этой статьей класса "Гуру недели" "Монолит" .

1 голос
/ 23 октября 2008
  • Наследование (как вы указали) или
  • Использовать функцию вместо метода или
  • Измените сам код движка, но изолируйте и управляйте изменениями, используя менеджер патчей, например quilt или Mercurial / MQ

Я не вижу, что не так с наследованием в этом контексте.

1 голос
/ 23 октября 2008

Если новый метод будет реализован с использованием существующего открытого интерфейса, то, возможно, он более объектно-ориентирован, чтобы он был отдельной функцией, а не методом. По крайней мере, Скотт Мейерс утверждает, что это так.

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

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

1 голос
/ 23 октября 2008

Звучит как отношение «действует на», которое не вписывается в наследство (используйте экономно!).

Один из вариантов - это служебный класс композиции, который воздействует на определенный экземпляр «Engine», создав его экземпляр с указателем на него.

0 голосов
/ 23 октября 2008

Для меня это звучит как классическая проблема наследования. За исключением того, что я поместил бы код в каталог «Расширения движка» и включил эту концепцию в вашу архитектуру.

0 голосов
/ 23 октября 2008

Или Категории в Цель C .

Существуют концептуальные подходы к расширению архитектуры классов (не отдельных классов) в C ++, но это не случайный акт, и требует планирования заранее. К сожалению.

0 голосов
/ 23 октября 2008

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

Вы также можете «притвориться» более динамичным языком и иметь массив обратных вызовов в качестве «методов» и создать способ вызывать их с помощью шаблонов или макросов и помещать «this» в стек перед остальной частью параметры. Но это было бы безумием:)

0 голосов
/ 23 октября 2008

Звучит так, будто ты хочешь Ruby Mixins. Не уверен, что есть что-то близкое в C ++. Я думаю, что вы должны сделать наследство.

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

...