Статический метод Const изменяет значения

Я экспериментировал с ключевым словом const и пытался извлечь из него полезный подход.

#include <iostream>

class A
{
  public:
  static const void modify(float& dummy)
  {
    dummy = 1.5f;
  }  
};

int main(int argc, char* argv[])
{
  auto a = 49.5f;

  A::modify(a);

  std::cout << a << std::endl; 

  return(0);
}

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

Что мне здесь не хватает? Как я могу разработать методы, которые не будут изменять значения аргументов?


person user1802174    schedule 09.11.2012    source источник
comment
Ха, я не знал, что вы можете применить const к void.   -  person chris    schedule 09.11.2012
comment
на самом деле вы имеете в виду static const void mod (const float & dummy)? в этом случае вы не можете изменить манекен   -  person billz    schedule 09.11.2012
comment
@chris Как я могу написать аналогичный метод, который может сохранять мои аргументы постоянными? почему я не получаю предупреждение?   -  person user1802174    schedule 09.11.2012
comment
Эй, смотрите, что я получаю от GCC: предупреждение: квалификаторы типа игнорируются при возвращаемом типе функции [-Wignored-qualifiers]   -  person chris    schedule 09.11.2012
comment
@billz да, но я сомневаюсь в использовании const для типа самого метода.   -  person user1802174    schedule 09.11.2012
comment
@user1802174 user1802174, const относится только к тому, что рядом с ним.   -  person chris    schedule 09.11.2012
comment
@chris Я абсолютно ничего не получаю от g++-4.7 -std=c++11   -  person user1802174    schedule 09.11.2012
comment
@ user1802174, это, вероятно, часть -Wall или -Wextra.   -  person chris    schedule 09.11.2012
comment
@chris, так что нет возможности использовать const для методов void?   -  person user1802174    schedule 09.11.2012
comment
@user1802174 user1802174, это относится только к части void, что совершенно бесполезно, так как вы все равно ничего не можете сделать с void. Не существует общего синтаксиса для того, чтобы сделать каждый параметр постоянным. Вы должны вручную применить его к каждому из них.   -  person chris    schedule 09.11.2012
comment
@chris, так как вы все равно ничего не можете сделать с пустотой. ну, не совсем потому, что смысл сделать каждый метод константным состоит в том, чтобы получить такое предупреждение, и с помощью пустоты я могу делать те же ошибки, что и со всеми другими подписями...   -  person user1802174    schedule 09.11.2012


Ответы (2)


  1. Объявленный вами метод не является const. Он возвращает const void (что бы это ни было), но сам по себе не является const-методом.

  2. Если бы было объявлено

    void modify(float& dummy) const
    

    это был бы const-метод, но в то же время он мог бы изменить значение аргумента, потому что const-метод может это делать. Единственное, что ему не разрешено делать, это изменять значения членов класса, к которому он принадлежит.

  3. Обратите внимание, что для объявления метода const мне пришлось удалить спецификацию static. Метод static никогда не может быть const, потому что статический метод все равно не может изменять какие-либо члены.

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

    static void modify(const float& dummy)
    

Чтобы проиллюстрировать, что может и что не может делать const-метод, вот класс, который имеет член и const-функцию:

class A
{
  float my_member;
public:
  void modify(float& dummy) const
  {
    my_member = dummy; // attempt to modify member -> illegal
    dummy = 1.5f;      // modifies a non-const argument -> ok
  }  
};

Как видите, он не может изменить член, но может изменить значение своего аргумента. Если вы хотите предотвратить это, вам нужно сделать аргумент const:

class A
{
  float my_member;
public:
  void modify(const float& dummy) const
  {
    my_member = dummy; // attempt to modify member -> illegal
    dummy = 1.5f;      // attempt to modify a const reference -> illegal
  }  
};
person jogojapan    schedule 09.11.2012
comment
так что пункт 4 - единственное решение для этого и всех методов пустоты? - person user1802174; 09.11.2012
comment
Нет, чтобы предотвратить изменение аргумента. - person Denis Ermolin; 09.11.2012
comment
@ user1802174, это единственное решение для каждой функции. Тип возвращаемого значения не имеет к этому никакого отношения. - person chris; 09.11.2012
comment
@chris Я был убежден, что использование const может положить каждый аргумент в сейф. наверное это не... - person user1802174; 09.11.2012
comment
@user1802174 user1802174, Можно по отдельности, но действительно некуда его поставить, что все равно не будет двусмысленно с чем-то другим. - person chris; 09.11.2012
comment
У меня была такая же реакция на «const void» - не уверен, что это должно быть. Поскольку «const void» почти всегда может быть ошибкой, я надеюсь, что разумный компилятор предупредит об этом, но, похоже, это не так. - person Nik Bougalis; 09.11.2012
comment
@НикБ. Как (почти) всегда, когда мы чем-то озадачены, кто-то был озадачен раньше: точка const void"> stackoverflow.com/questions/5057987/ - person jogojapan; 09.11.2012
comment
Я знаю, я не был озадачен; имеет смысл не определять в стандарте специальный случай для const void. Но это не значит, что компиляторы не должны предупреждать о чем-то подобном, даже если, строго говоря, это соответствует стандартам. - person Nik Bougalis; 09.11.2012

Вы неправильно понимаете, что делает 'const' в этом случае и как он работает.

Во-первых, в C++ статические функции-члены не могут быть константами. Функция, которую вы показываете, возвращает тип «const void» (имеет ли это смысл и должен ли компилятор предупреждать, это другая тема).

Во-вторых, параметр, который вы меняете, не является константой. Если 'modify' не была статической функцией и имела модификатор 'const' в функции, манекен все равно мог быть изменен:

void modify_nonstatic(float &dummy) const
{
    dummy = 1.5f; // perfectly fine - dummy isn't a member of
                  // the class and can be modified
}

Если вы хотите, чтобы параметр был константным, сделайте параметр константным:

static void modify(const float &dummy) 
{
    dummy = 1.5f; // fail! you can't modify a const.
}

void modify_nonstatic(const float &dummy)
{
    dummy = 1.5f; // fail! you can't modify a const.
}
person Nik Bougalis    schedule 09.11.2012
comment
спасибо, к сожалению, из-за моей низкой репутации я не могу проголосовать за это, но это хороший ответ, спасибо. - person user1802174; 09.11.2012
comment
Не беспокойтесь - дело не в голосах; речь идет о вопросах и ответах. - person Nik Bougalis; 09.11.2012