Что означает явное ключевое слово?

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

// get home dir of app, use MYAPPHOME env var if present, else executable dir.
func exeDir() string {
    dir, exists := os.LookupEnv("MYAPPHOME")
    if exists {
        return dir
    } else {
        ex, err := os.Executable()
        if err != nil {
            panic(err)
        }
        exPath := path.Dir(ex)
        return exPath
    }
}
2683
задан Ronny Brendel 24 January 2018 в 22:44
поделиться

4 ответа

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

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

class Foo
{
public:
  // single parameter constructor, can be used as an implicit conversion
  Foo (int foo) : m_foo (foo) 
  {
  }

  int GetFoo () { return m_foo; }

private:
  int m_foo;
};

Вот простая функция, которая берет Foo объект:

void DoBar (Foo foo)
{
  int i = foo.GetFoo ();
}

и вот то, где эти DoBar функция вызвана.

int main ()
{
  DoBar (42);
}

аргумент не Foo объект, а int. Однако там существует конструктор для Foo, который берет int, таким образом, этот конструктор может использоваться для преобразования параметра в корректный тип.

компилятору позволяют сделать это однажды для каждого параметра.

Добавление префикса explicit ключевое слово конструктору препятствует тому, чтобы компилятор использовал того конструктора для неявных преобразований. Добавление его к вышеупомянутому классу создаст ошибку компилятора при вызове функции DoBar (42). Теперь необходимо призвать к преобразованию явно с [1 111]

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

  • Вы имеете MyString(int size) класс с конструктором, который создает строку данного размера. У Вас есть функция print(const MyString&), и Вы звоните print(3) (когда Вы на самом деле намеревались звонить print("3")). Вы ожидаете, что это распечатает "3", но это печатает пустую строку длины 3 вместо этого.
3094
ответ дан 17 revs, 15 users 64% 25 January 2018 в 08:44
поделиться
  • 1
    Я могу использовать create вместо udpate, или я должен использовать обоих? – Billie 12 January 2014 в 12:11

Предположим, у Вас есть класс String:

class String {
public:
    String(int n); // allocate n bytes to the String object
    String(const char *p); // initializes object with char *p
};

Теперь, если Вы пробуете:

String mystring = 'x';

символ 'x' будет неявно преобразован в int и затем String(int), конструктора вызовут. Но, это не то, что, возможно, предназначил пользователь. Так, для предотвращения таких условий мы определим конструктора как explicit:

class String {
public:
    explicit String (int n); //allocate n bytes
    String(const char *p); // initialize sobject with string p
};
1068
ответ дан Azeem 25 January 2018 в 08:44
поделиться
  • 1
    просто создайте, достаточно впервые, и затем возвратите его для обновления для будущего – tesnik03 12 January 2014 в 12:13

В C++ конструктора только с одним обязательным параметром считают неявной функцией преобразования. Это преобразовывает тип параметра в тип класса. Является ли это хорошей вещью или не зависит от семантики конструктора.

, Например, если у Вас есть строковый класс с конструктором String(const char* s), это, вероятно, точно, что Вы хотите. Можно передать const char* функции, ожидая String, и компилятор автоматически создаст временный файл String объект для Вас.

, С другой стороны, если у Вас есть буферный класс, конструктор которого Buffer(int size) берет размер буфера в байтах, Вы, вероятно, не хотите, чтобы компилятор бесшумно превратил int с в Buffer с. Для предотвращения этого Вы объявляете конструктора с explicit ключевое слово:

class Buffer { explicit Buffer(int size); ... }

Тот путь,

void useBuffer(Buffer& buf);
useBuffer(4);

становится ошибкой времени компиляции. Если Вы хотите передать временный файл Buffer объект, необходимо сделать так явно:

useBuffer(Buffer(4));

, Таким образом, если Ваш конструктор единственного параметра преобразовывает параметр в объект Вашего класса, Вы, вероятно, не хотите использовать explicit ключевое слово. Но если у Вас есть конструктор, который просто, оказывается, берет единственный параметр, необходимо объявить, что это как [1 113] препятствует тому, чтобы компилятор удивил Вас неожиданными преобразованиями.

149
ответ дан cjm 25 January 2018 в 08:44
поделиться

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

Кроме того, всегда полезно создавать конструкторы с одним аргументом (включая те, которые имеют значения по умолчанию для arg2, arg3, ...), как уже говорилось . Как всегда с C ++: если вы этого не сделаете - вы захотите, чтобы вы это сделали ...

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

18
ответ дан 22 November 2019 в 19:51
поделиться
Другие вопросы по тегам:

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