Как Вы правильно используете пространства имен в C++?

Swift 2.x ответ, который загружает изображение в файл (в отличие от ответа Лео Дабуса, в котором хранится изображение в памяти). На основании ответа Льва Дабуса и ответа Роба из Получить данные из NSURLSession DownloadTaskWithRequest из обработчика завершения :

    // Set download vars
    let downloadURL = NSURL() // URL to download from
    let localFilename = "foobar.png" // Filename for storing locally 

    // Create download request
    let task = NSURLSession.sharedSession().downloadTaskWithURL(downloadURL) { location, response, error in
        guard location != nil && error == nil else {
            print("Error downloading message: \(error)")
            return
        }

        // If here, no errors so save message to permanent location
        let fileManager = NSFileManager.defaultManager()
        do {
            let documents = try fileManager.URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: false)
            let fileURL = documents.URLByAppendingPathComponent(localFilename)
            try fileManager.moveItemAtURL(location!, toURL: fileURL)
            self.doFileDownloaded(fileURL, localFilename: localFilename)
            print("Downloaded message @ \(localFilename)")
        } catch {
            print("Error downloading message: \(error)")
        }
    }

    // Start download
    print("Starting download @ \(downloadURL)")
    task.resume()


// Helper function called after file successfully downloaded
private func doFileDownloaded(fileURL: NSURL, localFilename: String) {

    // Do stuff with downloaded image

}

229
задан Philipp Matthias Schäfer 22 May 2014 в 23:11
поделиться

15 ответов

Пространства имен являются пакетами по существу. Они могут использоваться как это:

namespace MyNamespace
{
  class MyClass
  {
  };
}

Тогда в коде:

MyNamespace::MyClass* pClass = new MyNamespace::MyClass();

Hope, которая помогает.

Или, если Вы хотите всегда использовать определенное пространство имен, можно сделать это:

using namespace MyNamespace;

MyClass* pClass = new MyClass();

Редактирование: После того, что сказал bernhardrusch, я склонен не использовать "синтаксис" пространства имен x использования вообще, я обычно явно определяю пространство имен при инстанцировании моих объектов (т.е. первый пример, который я показал).

И поскольку Вы спросили ниже , можно использовать столько пространств имен, сколько Вам нравится.

163
ответ дан Community 23 November 2019 в 03:43
поделиться

Другое различие между Java и C++, то, что в C++, иерархии пространства имен не нужно Маху расположение файловой системы. Таким образом, я склонен помещать всю допускающую повторное использование библиотеку в единое пространство имен и подсистемы в библиотеке в подкаталогах:

#include "lib/module1.h"
#include "lib/module2.h"

lib::class1 *v = new lib::class1();

я только поместил бы подсистемы во вложенные пространства имен, если бы была возможность конфликта имен.

2
ответ дан Nick 23 November 2019 в 03:43
поделиться

Я использовал пространства имен C++ тем же путем, я делаю в C#, Perl, и т.д. Это - просто семантическое разделение символов между стандартным материалом библиотеки, сторонним материалом и моим собственным кодом. Я поместил бы свое собственное приложение в одно пространство имен, затем допускающий повторное использование компонент библиотеки в другом пространстве имен для разделения.

2
ответ дан spoulson 23 November 2019 в 03:43
поделиться

Обратите внимание, что пространство имен в C++ действительно является просто пространством имен. Они не обеспечивают ни одной инкапсуляции, которую пакеты делают в Java, таким образом, Вы, вероятно, не будете использовать их как очень.

3
ответ дан Kristopher Johnson 23 November 2019 в 03:43
поделиться

Я предпочитаю использовать пространство имен верхнего уровня для приложения и sub пространства имен для компонентов.

способ, которым можно использовать классы от других пространств имен, удивительно очень похож на путь в Java. Можно или использовать "ПРОСТРАНСТВО ИМЕН использования", которое подобно "оператору" ПАКЕТА импорта, например, используйте станд., Или Вы определяете пакет как префикс класса, разделенного с "::", например, станд.:: строка. Это подобно "java.lang. Строка" в Java.

3
ответ дан dmeister 23 November 2019 в 03:43
поделиться

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

3
ответ дан Adam Hollidge 23 November 2019 в 03:43
поделиться

marius

Да, можно использовать несколько пространств имен за один раз, например:

using namespace boost;   
using namespace std;  

shared_ptr<int> p(new int(1));   // shared_ptr belongs to boost   
cout << "cout belongs to std::" << endl;   // cout and endl are in std

[февраль 2014 - (Это действительно было это долго?): Этот конкретный пример теперь неоднозначен, как Joey указывает ниже. Повышение и станд.:: теперь у каждого есть shared_ptr.]

5
ответ дан Community 23 November 2019 в 03:43
поделиться

Можно также содержать "пространство имен использования..." в функции, например:

void test(const std::string& s) {
    using namespace std;
    cout << s;
}
5
ответ дан Shadow2531 23 November 2019 в 03:43
поделиться

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

namespace MyNamespace
{
    double square(double x) { return x * x; }
}

в файле square.h, и

namespace MyNamespace
{
    double cube(double x) { return x * x * x; }
}

в файле cube.h. Это определяет единое пространство имен MyNamespace (то есть, можно определить единое пространство имен через несколько файлов).

18
ответ дан perror 23 November 2019 в 03:43
поделиться

Большие проекты C++ я видел едва используемый больше чем одно пространство имен (например, стимулируйте библиотеку).

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

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

Другое использование (никакая предназначенная игра слов) пространств имен, что я использую много, является анонимным пространством имен:

namespace {
  const int CONSTANT = 42;
}

Это - в основном то же как:

static const int CONSTANT = 42;

Используя анонимное пространство имен (вместо помех) однако рекомендуемый путь к коду и данным, чтобы быть видимым только в текущей единице компиляции в C++.

36
ответ дан 23 November 2019 в 03:43
поделиться

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

Они важны, потому что они, как полагает компилятор, применяют интерфейсный принцип. В основном это может быть объяснено примером:

namespace ns {

class A
{
};

void print(A a)
{
}

}

, Если бы Вы хотели распечатать объект, код был бы этим:

ns::A a;
print(a);

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

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

namespace ns {

class A
{
};

}

void print(A a)
{
}

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

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

И вот почему необходимо рассмотреть пространство имен C++ как "интерфейс", когда Вы используете один и имеете в виду интерфейсный принцип.

, Если Вы хотите лучшее объяснение этого поведения, можно отослать к книге Исключительный C++ от Herb Sutter

54
ответ дан Dan 23 November 2019 в 03:43
поделиться

Vincent Robert прав в своем комментарии , Как Вы правильно используете пространства имен в C++? .

Используя Пространства имен пространства имен

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

В C++, Вы могли дать пространство имен всему коду в Вашем модуле. Например, для модуля MyModule.dll, Вы могли дать его коду пространство имен MyModule. Я имею, посмотрите в другом месте кого-то использование MyCompany:: MyProject:: MyModule. Я предполагаю, что это - излишество, но в целом, это кажется корректным мне.

Используя "использование"

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

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

самый безопасный способ использовать "использование" состоит в том, чтобы импортировать избранные символы:

void doSomething()
{
   using std::string ; // string is now "imported", at least,
                       // until the end of the function
   string a("Hello World!") ;
   std::cout << a << std::endl ;
}

void doSomethingElse()
{
   using namespace std ; // everything from std is now "imported", at least,
                       // until the end of the function
   string a("Hello World!") ;
   cout << a << endl ;
}

Вы будете видеть большое "использование станд. пространства имен"; в учебном руководстве или примерах кода. Причина состоит в том, чтобы сократить количество символов для создания чтения легче, не потому что это - хорошая идея.

"станд. пространства имен использования"; препятствуется Scott Meyers (я не помню точно, какую книгу, но я могу найти им при необходимости).

Пространства имен Состава

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

В "Специальном выпуске", по телефону 8.2.8 Состав Пространства имен, он описывает, как можно объединить два пространства имен AAA и BBB в другой названный CCC. Таким образом CCC становится псевдонимом и для AAA и для BBB:

namespace AAA
{
   void doSomething() ;
}

namespace BBB
{
   void doSomethingElse() ;
}

namespace CCC
{
   using namespace AAA ;
   using namespace BBB ;
}

void doSomethingAgain()
{
   CCC::doSomething() ;
   CCC::doSomethingElse() ;
}

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

77
ответ дан Mercer 23 November 2019 в 03:43
поделиться

Чтобы постараться не говорить все, Mark Ingram уже сказал немного подсказки для использования пространств имен:

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

я думаю, что пространства имен главным образом используются для предотвращения конфликтов имен - не обязательно для организации структуры кода. Я организовал бы программы C++ главным образом с заголовочными файлами / файловая структура.

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

Дополнительное примечание к директиве использования: Некоторые люди предпочитают использовать "использование" только для единственных элементов:

using std::cout;  
using std::endl;
114
ответ дан Lazer 23 November 2019 в 03:43
поделиться

В Java:

package somepackage;
class SomeClass {}

В C++:

namespace somenamespace {
    class SomeClass {}
}

И использование их, Java:

import somepackage;

И C++:

using namespace somenamespace;

кроме того, полные имена "somepackge. SomeClass" для Java и "somenamespace:: SomeClass" для C++. Используя те соглашения, можно организовать как Вы, привыкли к в Java, включая создание соответствия именам папок для пространств имен. Папка-> пакет и файл-> требования класса не там, хотя, таким образом, можно назвать папки и классы независимо от пакетов и пространств имен.

11
ответ дан Staale 23 November 2019 в 03:43
поделиться

Я не видел упоминания об этом в других ответах, поэтому вот мои 2 канадских цента:

В теме «Использование пространства имен» полезным утверждением является псевдоним пространства имен, позволяя вам «переименовать» пространство имен, как правило, чтобы дать ему более короткое имя. Например, вместо:

Some::Impossibly::Annoyingly::Long:Name::For::Namespace::Finally::TheClassName foo;
Some::Impossibly::Annoyingly::Long:Name::For::Namespace::Finally::AnotherClassName bar;

вы можете написать:

namespace Shorter = Some::Impossibly::Annoyingly::Long:Name::For::Namespace::Finally;
Shorter::TheClassName foo;
Shorter::AnotherClassName bar;
71
ответ дан 23 November 2019 в 03:43
поделиться
Другие вопросы по тегам:

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