Стиль программирования на C++

Это стало сообщением об ошибке StyleBook (формулировка должна быть более информативной, верно).

Ошибка была вызвана тем, что TFormLogin имел ссылки на StyleBook и ссылки StyleLookup и StyleName, указанные в FMX, тогда как в StyleBook не было соответствующего стиля StyleName.

P.S. Что меня озадачивает, когда StyleLookup или StyleName понятны, код работает нормально. Когда оба заполнены - появляется сообщение об ошибке.

12
задан asantacreu 30 March 2018 в 17:33
поделиться

16 ответов

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

1) Большие единицы перевода приводят к более длительному времени компиляции и большим размерам объектного файла.

2) Круговые зависимости! И это - большое. И это может почти всегда фиксироваться путем разделения заголовков и источника:

// Vehicle.h
class Wheel {
    private:
        Car& m_parent;
    public:
        Wheel( Car& p ) : m_parent( p ) {
            std::cout << "Car has " << m_parent.numWheels() << " wheels." << std::endl;
        }
};

class Car {
    private:
        std::vector< Wheel > m_wheels;
    public:
        Car() {
            for( int i=0; i<4; ++i )
                m_wheels.push_back( Wheel( *this ) );
        }

        int numWheels() {
            return m_wheels.size();
        }
}

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

Но если Вы будете разделять их на надлежащий.h и .cpp файлы и будете использовать предописания, то он удовлетворит компилятор:

//Wheel.h
//-------
class Car;

class Wheel {
private:
    Car& m_parent;
public:
    Wheel( Car& p );
};

//Wheel.cpp
//---------
#include "Wheel.h"
#include "Car.h"

Wheel::Wheel( Car& p ) : m_parent( p ) {
        std::cout << "Car has " << m_parent.numWheels() << " wheels." << std::endl;
}

//Car.h
//-----
class Wheel;

class Car {
private:
    std::vector< Wheel > m_wheels;
public:
    Car();
    int numWheels();
}

//Car.cpp
//-------
#include "Car.h"
#include "Wheel.h"

Car::Car() {
        for( int i=0; i<4; ++i )
            m_wheels.push_back( Wheel( *this ) );
}

int Car::numWheels() {
        return m_wheels.size();
}

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

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

Положите, что C++ имеет причину этой идиомы, потому что, если Вы не, Вы сделаете много головных болей для себя по линии. Я знаю:/

24
ответ дан 2 December 2019 в 02:49
поделиться

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

Кроме того, C++ и Java являются двумя различными языками и должны использоваться по-разному. Существуют причины заголовочных файлов (думайте о нем как об объявлении интерфейса), например.

1
ответ дан 2 December 2019 в 02:49
поделиться

Стиль, в котором Вы программируете, ваше дело. Просто удостоверьтесь, что Вы понимаете, что "уродливые" другие стиля используют.

1
ответ дан 2 December 2019 в 02:49
поделиться

Я думаю, что многие программисты получают первый опыт с продуктами Microsoft (и их пример кода) и/или программирующий для Windows API и ранней Microsoft, кодирующей конвенции, которые использовались во фрагменте кода в Вашем вопросе (Т.е. Венгерская запись, капитализация определенных типов, и т.д.). Я ненавижу рассмотрение исходного кода от Microsoft, которая похожа на него, был выполнен через поперечный уничтожитель бумаги и склеил назад. Но ужасная конвенция кодирования не является функцией или отражением языка C++, который я нахожу не более красивыми или ужасными, чем большинство других языков.

На самом деле я нахожу синтаксис C++ с минимальными ключевыми словами, фигурные скобки и богатый набор символьных операторов служит, чтобы не отвлечь от или вытеснить важный материал: мои переменные, мой тип defs, мои методы; который, конечно, позволяет мне делать самый красивый код из всех :-)

2
ответ дан 2 December 2019 в 02:49
поделиться

Я волнуюсь от тона Вашего вопроса, что можно читать некоторый плохой код C++ в изучении C++. Правильно написанный код обычно не ужасен на любом языке. Как начальная точка, Вы могли бы попробовать C++ онлайн FAQ, особенно глава по изучению C++.

1
ответ дан 2 December 2019 в 02:49
поделиться

Это не ужасно вообще. Я сказал бы, что это... mhhh отличающееся. Принося Ваш старый стиль к новой платформе, это ужасно (у меня было много дискуссий об этом с г-ном Skeet).

Помните, что Java был определенными годами после C++, таким образом, разумно, что они починили некоторые конструкции (тем же способом, который C# узнают из Java).

Так, я предложил бы сохранить в том стиле C++.

Думайте об этом. Заголовочные файлы похожи на объявления интерфейса, и cpp файлы являются реализацией.

Я думаю, что C++ не имеет "интерфейсного" ключевого слова, и это - способ, которым Вы разделяете интерфейс класса от его реализации. Подобный этому в Java:

public interface Some { 
    public void method();
}

public class SomeImpl implements Some { 
    public void method(){}
}
3
ответ дан 2 December 2019 в 02:49
поделиться

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

Таким образом, наконец есть ли любая причина для меня продолжить эту резню к ООП

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

C++ является языком мультипарадигмы, не только OO langage. Шаблоны являются формой универсального программирования, к которому можно относиться процедурное, ООП и парадигмы метапрограммирования C++. Со следующим стандартом C++ Вы будете видеть некоторые функциональные парадигмы, добавленные также.

Все это помещения определения класса в заголовочном файле и методов в файле другого источника;

Это возникает с языка программирования C, назад в 70-х. C++ был разработан, чтобы быть назад совместимым с C.

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

Если Вы хотите убежать из мышления ООП, попробуйте D! Затем когда Вы получаете чувство для того, как к смешиванию и подгонке различные парадигмы, Вы можете (если Вы, так требуйте), возвращаются к C++ и учатся иметь дело с его синтаксисом и другими бедами.

P.S. Я ежедневно использую C++, и я - поклонник его - это - мой любимый язык программирования. Но поскольку любой опытный программист на C++ знает, C++ действительно имеет свои беды. Но после того как Вы осваиваете различные парадигмы и знаете, как работать вокруг бед C++, у Вас будет невероятно мощный инструмент (для этого, весь, язык), в Вашем распоряжении.

Удача в Ваших приключениях!

6
ответ дан 2 December 2019 в 02:49
поделиться

Как стереотипный программист, который программирует в одной определенной парадигме, Вы решили, что определенные вещи, которые не знакомы с Вами, просто ужасны.

C++ является другим языком, это - мультипарадигма, и он имеет много переносов от C. Как другой указали, это - просто способ, которым это.

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

Если Вы не верите мне, пошли посмотреть на некоторые Модификации там для игр. Совершенно возможно найти заголовочный файл CryEngine2 где-нибудь, потому что модификации Crysis должны были бы говорить с ним, но это не должно понимать, как это работает. Заголовочные файлы определят, как в конечном счете функция вызова должна установить стек для вызывания другой функции.

Чтобы не быть condensending, но я думаю, в чем Вы действительно нуждаетесь, должен программировать в чем-то совершенно другом. Исследуйте другие парадигмы, и найдите некоторые языки и начните писать некоторые игрушечные приложения. Сначала, вещи выглядели бы ужасными, но Вы будете в конечном счете видеть преимущества.

Я сказал то же самое о функциональном программировании также. Теперь я жалуюсь на то, как PHP забил функциональное программирование с массивами.

3
ответ дан 2 December 2019 в 02:49
поделиться

Отдельное объявление и определение являются наименьшим количеством различий между C++ и Java. Существенным различием в современном C++ является важность "семантики значения".

Из-за отсутствия сборки "мусора", но превосходной поддержки создания типов, которые ведут себя как автономные значения, хороший стиль C++ включает пишущие типы значения хорошего поведения, с последовательной конструкцией, конструкцией копии, присвоением, подкачкой и разрушением.

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

Посмотрите на то, как стандартная библиотека C++ работает, и как она ожидает, что Ваши типы будут вести себя.

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

3
ответ дан 2 December 2019 в 02:49
поделиться

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

Это действительно плохо в Windows, где Вы сталкиваетесь с вещами как различные средства выделения "кучи" в различных частях программы и если Вы измените реализацию, то вызывающие стороны Вашего DLL будут использовать старый код от встроенных заголовков.

3
ответ дан 2 December 2019 в 02:49
поделиться

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

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

9
ответ дан 2 December 2019 в 02:49
поделиться

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

Я нахожу, что наличие всего в одном файле в Java дезорганизовано. Так, каждый к их собственному.

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

Я думаю, лучше Java (как глагол), когда Вы пишете Java, и к C++ когда Вы C++! Вы будете ценить почему с опытом языка. То же как переключающийся на любой новый язык.

11
ответ дан 2 December 2019 в 02:49
поделиться

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

Однако Вы будете вполне рады узнать, что многие разработчики C++ соглашаются с Вами в этом отношении. Так идут вперед и помещенный Ваша вся реализация в *.h файлы. Существует школа стиля там, который соглашается с Вами.

8
ответ дан 2 December 2019 в 02:49
поделиться

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

Таким образом, это - вопрос удобства.


Править:

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

  • что класс может сделать (его интерфейс, данный его объявлением)
  • как класс делает это (его реализация)

Не будучи способен делать это или в C# или в Java довольно печально, особенно когда у меня нет Intellisense под рукой.

3
ответ дан 2 December 2019 в 02:49
поделиться

Когда код создает, препроцессор C++ создает единицу перевода. Это запускается с .cpp файла, анализирует #includes, захватывая текст от заголовков и генерирует один большой большой текстовый файл со всеми заголовками и кодом .cpp. Затем эта единица перевода компилируется в код, который будет работать на платформе, для которой Вы нацелены. Каждая единица перевода заканчивается как один объектный файл.

Так.h файлы включены в несколько единиц перевода, и .cpp файл просто включен в один.

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

Так.. уменьшение материала в.h файлах решительно улучшает время компиляции. Можно отредактировать .cpp файл для изменения функции, и только что одна единица перевода должна быть восстановлена.

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

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

16
ответ дан 2 December 2019 в 02:49
поделиться

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

Так или иначе я просто хотел отправить с другой стороны вопроса: действительно ли C++ является резней ООП?

C++ является языком мультипарадигмы. Это позволяет процедурное, объектно-ориентированное и универсальное программирование. И это - достоинство, не дефект. Можно все еще использовать чистое ООП, при необходимости но Ваш код, конечно, извлечет выгоду из изучения и знания, когда использовать другие парадигмы.

Как пример, мне не нравятся служебные классы, где все функции членства статичны, и нет никаких данных. Нет никакой причины создать служебный класс больше, чем просто группирующийся ряд бесплатных функций под общим названием. Необходимо сделать это в Java, поскольку это настаивает на чистом синтаксисе OO, который, как прокомментировано Tom, не является тем же как реальным OO. В C++, определяющем пространство имен и ряд бесплатных функций, предлагает аналогичное решение без Вас бывший должный заблокировать создание объектов, объявляя частного конструктора или иначе позволяя пользователям инстанцировать объектов ерунды от пустого класса.

Мне опыт (я был однажды программист только для Java) учил меня, что существуют различные инструменты, которые лучше соответствуют различным проблемам. Я должен все же найти золотой молоток, и преимущество C++ состоит в том, что можно выбрать другой молоток для каждой различной задачи, даже в той же единице компиляции.

Исправление: litb сообщает мне в комментарии, что WNDCLASS является структурой в win32 API. Так, чтобы критика класса, не используя списки инициализации была простой ерундой и как таковой, я удаляю его.

10
ответ дан 2 December 2019 в 02:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: