Почему классы на C++ должны объявлять свои частные функции? Имеет ли это фактические технические причины (какова его роль во время компиляции) или просто для согласованности?C++: зачем объявлять частные функции?
ответ
Я спросил, почему частные функции должны были быть объявлены на всех, так как они ничего (ни размер объекта, ни виртуальной таблицы записи) для других единиц перевода знать
не добавляют Если вы думаете об этом , это похоже на объявление некоторых функций static
в файле. Это не видно снаружи, но это важно для самого компилятора. Компилятор хочет знать подпись функции до ее использования. Вот почему вы объявляете функции в первую очередь. Помните, что компиляторы C++ имеют один проход, что означает, что все должно быть объявлено до его использования.
С точки зрения программиста объявление частных функций по-прежнему не является абсолютно бесполезным. Представьте себе 2 класса, один из которых - friend
другого. Дружеский класс должен знать, как выглядят рядовые участники этого класса (это обсуждение становится странным), иначе они не смогут его использовать.
Что касается того, почему именно C++ был разработан таким образом, я бы сказал, что есть историческая причина: тот факт, что вы не можете нарезать структуру на C, был принят C++, поэтому вы не можете нарезать класс (и принят другими языками, разветвленными с C++).Я также предполагаю, что речь идет о простоте: представьте себе, насколько сложно было бы разработать метод компиляции, в котором вы можете разделить класс между различными файлами заголовков, сообщить об этом своим исходным файлам и не позволять другим добавлять материал в ваш класс.
Заключительное примечание состоит в том, что private
функции могут влиять на размер vtable. То есть, если они virtual
.
На самом деле не совсем. Если у вас встроенные функции в классе, они могут ссылаться на функции, которые позже определены в одном классе. Но, вероятно, идея начиналась с одного прохода, и это исключение позже было добавлено к нему.
Это, в частности, элементы-члены.
Да, я привык скрывать реализацию на C с помощью статических функций C, поэтому я бы просто объявил (до любая реализация) частные функции внутри cpp отдельно от остальных, так же как статические объявления в C – Ancurio
Случай использования «друга», однако, является допустимой точкой. Благодарю. – Ancurio
@ Анукурио, хотя то, что вы говорите, имеет смысл, к сожалению, нет поддержки от C++, чтобы нарезать определение класса на две части. – Shahbaz
Уровень доступа не влияет на видимость. Частные функции могут видеть внешний код и могут быть выбраны разрешением перегрузки (который затем приведет к ошибке violoation доступа):
class A {
void F(int i) {}
public:
void F(unsigned i) {}
};
int main() {
A a;
a.F(1); // error, void A::F(int) is private
}
себе путаницу, когда это работает:
class A {
public:
void F(unsigned i) {}
};
int main() {
A a;
a.F(1);
}
// add private F overload to A
void A::F(int i) {}
Но изменить его к первому коду вызывает разрешение перегрузки для выбора другой функции. А как насчет следующего примера?
class A {
public:
void F(unsigned i) {}
};
// add private F overload to A
void A::F(int i) {}
int main() {
A a;
a.F(1);
}
Или вот еще один пример этого происходит не так:
// A.h
class A {
public:
void g() { f(1); }
void f(unsigned);
};
// A_private_interface.h
class A;
void A::f(int);
// A.cpp
#include "A_private_interface.h"
#include "A.h"
void A::f(int) {}
void A::f(unsigned) {}
// main.cpp
#include "A.h"
int main() {
A().g();
}
Эх, это только указывает, что правила перегрузки должны измениться. – GManNickG
@GManNickG Чтобы получать видимость во внимание и не выбирать недоступные методы? У C++ есть все основания для того, как он работает. Например: http://stackoverflow.com/questions/644461/c-constructor-overloading-private-and-public – bames53
Я не думаю, что правила перегрузки должны были бы учитывать доступность. Они, вероятно, просто должны быть определены, чтобы учитывать только функции-члены, которые объявляются перед точкой использования, поэтому, если ваша функция частного члена находится в определении класса, то она останавливает 'aF (1)' компиляцию в клиентском коде , и если он добавлен только в 'A.cpp', то это не влияет на код клиента, но влияет на .cpp. Это уже то, как работают пространства имен (если вы добавляете больше перегрузок, они могут быть выбраны). Требуется некоторая сложность, например, что происходит с двухфазным поиском. –
Частные члены класса все еще члены класса, поэтому они должны быть объявлены, как реализация других государственных членов может зависеть по этому частному методу. Объявление их позволит компилятору понять вызов этой функции как вызов функции-члена.
Если у вас есть метод, который используется только в файле .cpp
и не зависит от прямого доступа к другим частным членам класса, подумайте над перемещением его в анонимное пространство имен. Затем его не нужно объявлять в файле заголовка.
Да, но _why спецификация говорит, что они должны быть объявлены? Вы не ответили на вопрос. Там уже есть правила, говорящие, что функции должны быть объявлены перед вызовом, так что это не так. (совет на языке имен хороший, хотя) –
Вы должны объявить всех членов в определении самого класса, чтобы компилятор знал, какие функции разрешено быть членами. В противном случае второй программист мог (случайно?) Прийти и добавить членов, совершить ошибки и нарушить гарантии вашего объекта, вызывая неопределенное поведение и/или случайные сбои.
Я думаю, что вы только что описали классы Python =) – JoeFish
Существует несколько причин, почему частные функции должны быть объявлены.
Первое время компиляции Проверка ошибок
точка модификаторов доступа, чтобы поймать определенные классы (не каламбур) ошибок программирования во время компиляции. Частные функции - это функции, которые, если кто-то назвал их вне класса, это будет ошибкой, и вы хотите узнать об этом как можно раньше.
Второй Casting и наследование
Взятые из стандарта C++:
3 [Примечание: Член частного базового класса может быть недоступен в качестве унаследованного имени элемента, но доступны непосредственно. Из-за правил конверсий указателей (4.10) и явных приведений (5.4) преобразование из указателя в производный класс в указатель на недоступный базовый класс может быть плохо сформировано, если используется неявное преобразование, но хорошо сформированное если используется явный литой.
3-й Друзья
Друзья показать друг другу там рядовыми. Частный метод может быть вызван другим классом, который является другом.
четвёртая Общие здравомыслие и Good Design
Ever работал над проектом еще 100 разработчиков. Наличие стандартного и общего набора правил помогает поддерживать ремонтопригодность. объявление чего-то частного имеет конкретное значение для всех остальных в группе.
Также это вступает в хорошие принципы проектирования ОО. Что разоблачить и то, что не
Это не хочет, чтобы Анкурио хотел знать. Он задается вопросом, почему мы не можем (некоторые) держать частные функции в качестве * секретного * в первую очередь. Вы не можете вызвать функцию, о которой вы не знаете. –
компилятор должен знать, что его личное. поэтому он может выдать предупреждение о компиляции, когда кто-то пытается его называть ... ничто никогда не является тайной –
@nate_weldon, это правда, но если частные не виртуальные функции не были объявлены в общедоступном заголовочном файле (и, следовательно, документация), в первую очередь, никто не попытался бы назвать это. За исключением, может быть, для себя ... в этом случае это предупреждение (не правда ли это на самом деле?) Имеет смысл. – Ancurio
Там это сочетание проблем, но:
- C++ не позволяет повторно открыть класс объявить новых членов в нем после его первоначального определения.
- C++ не позволяет вам иметь разные определения класса в разных единицах перевода, которые объединяются для формирования программы.
Поэтому:
- Любых частных функций-членов, что файл .cpp хочет объявленные в классе должен быть определен в файл .h, который каждый пользователь класса видит тоже.
С POV практической бинарной совместимости: как говорит Дэвид в комментариях, частные virtual
функций влияют на размере и расположение виртуальных таблиц этого класса и любые классы, которые используют его в качестве базы. Поэтому компилятор должен знать о них даже при компиляции кода, который не может их назвать.
Может ли C++ быть изобретен иначе, чтобы позволить .cpp-файлу повторно открывать класс и добавлять определенные виды дополнительных функций-членов, причем реализация требует, чтобы это не нарушало двоичную совместимость? Можно ли смягчить одно правило определения, чтобы определенные определения отличались определенным образом? Например, статические функции-члены и не виртуальные нестатические функции-члены.
Возможно, да для обоих. Я не думаю, что есть какие-либо технические препятствия, хотя в настоящее время ODR очень строго о том, что делает определение «отличным» (и, следовательно, очень велико для реализаций, позволяющих бинарную несовместимость между очень похожими определениями). Я думаю, что текст для введения такого исключения в правило будет сложным.
В конечном счете, это может свести к минимуму «дизайнеры хотели этого», или, возможно, кто-то попробовал это и столкнулся с препятствием, о котором я не думал.
Текущие предложения модулей имеют решения проблемы конфиденциальности, просто потому, что они добавляют еще один «слой» или «комнату» видимости: сам класс, модуль, «внешний код». 'private' будет просто не утечка вне определения модуля, и компилятор все еще может знать обо всем. – Xeo
«_C++ не позволяет вам повторно открывать класс для объявления новых членов в нем после его начального определения.» «Это неверно: 14.7.3 ** Явная специализация **' [temp.expl.spec] '" Явная специализация любого из следующего: (...) - шаблон класса-члена шаблона класса или класса - шаблон функции-члена шаблона класса или класса может быть объявлен объявлением (...) "" явная специализация объявляется в пространстве имен, охватывающих специализированный шаблон ». – curiousguy
@curiousguy: не уверен, что я последую за тобой. Я не думаю, что специализация шаблона-члена является «новым членом», так как шаблон является членом. Возможно, я ошибаюсь. Если я ошибаюсь, то, конечно, шаблоны являются исключением из того, что я говорил, поскольку так же, как специализированные шаблоны членов вне класса, вы можете, конечно, также * создавать экземпляры * шаблонов-членов вне класса. В любом случае я не думаю, что класс был «вновь открыт», и я не думаю, что он помогает эксперту. –
Одна из причин заключается в том, что в C++ друзья могут получить доступ к вашим рядовым. Друзья должны получить доступ к ним, друзья должны знать о них.
@Neal: Ну ... это чертова цель * друга. – Xeo
- 1. Зачем объявлять аргумент функции окончательным?
- 2. Интерфейс не может объявлять частные/защищенные функции
- 3. iOS: IBAction/Частные методы - зачем объявлять в .m под @interface?
- 4. Зачем объявлять функции прототипа вне наследуемого объекта?
- 5. Зачем нам нужно объявлять функции перед их использованием в C?
- 6. Зачем объявлять внутри $ (function() {...})?
- 7. Зачем объявлять jQuery дважды?
- 8. Зачем объявлять функцию C как статическую встроенную?
- 9. Объявлять частные статические члены в F #?
- 10. Нужно ли объявлять внутренние частные частные вложенные классы?
- 11. Зачем объявлять параметр массива типов?
- 12. Частные функции могут использоваться на рабочем столе
- 13. Зачем объявлять функцию этой многословной?
- 14. Зачем объявлять (некоторые) Spring-Beans
- 15. Зачем объявлять переменную вроде $ var = "";
- 16. Зачем объявлять интерфейс внутри интерфейса?
- 17. Зачем вам объявлять переменные в середине определения функции?
- 18. Зачем объявлять статическую переменную в основном?
- 19. Вам нужно объявлять функции в C?
- 20. Зачем объявлять функцию как переменную в php
- 21. Динамически объявлять имя функции?
- 22. Зачем объявлять целое число типа clock_t моей программой на C?
- 23. Зачем объявлять переменные как статические в методе класса Objective-c?
- 24. Зачем объявлять переменную или функцию static в C?
- 25. Зачем объявлять массив double для хранения целого числа (C++)
- 26. C++ называть частные функции в контейнерном классе
- 27. Как иметь частные функции в C++
- 28. Частные или статические функции в C++
- 29. JS: ООП частные функции/частные поля
- 30. Объявлять функции в ASP.NET WebPages
Вы спрашиваете, почему сами функции должны быть объявлены или вы спрашиваете, почему вы должны сказать «частные» для этих функций? – GManNickG
@GManNickG я думаю первый. –
@GManNickG 1-й. Я просто не знаю, почему другие классы, включая мой заголовок, должны знать о его частных функциях. – Ancurio