Перегрузка может возможна с двумя версиями функции, постоянной функции-члена и функции без констант - PullRequest
8 голосов
/ 16 июня 2010

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


//function which can modify member
String& MyClass::doSomething();

//constant member function
String& MyClass::doSomething() const;

Пожалуйста, дайте мне знать причину этого.

Ответы [ 5 ]

9 голосов
/ 17 июня 2010

Да, вы можете.

Если у вас есть

MyClass m;
m.doSomething();

Будет вызвана неконстантная версия.Если у вас есть

const MyClass m;
m.doSomething();

Будет вызвана константная версия.

3 голосов
/ 17 июня 2010

Простой способ понять это - представить объект, для которого вызывается метод, как 0-й параметр:

например: Подумайте о

 String& MyClass::doSomething();
 MyClass mc;
 mc.doSomething();

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

 String& MyClass_doSomething(MyClass *this);
 MyClass mc;
 MyClass_doSomething(&mc);

Теперь перегрузка, основанная на константности, является лишь частным случаем перегрузки по типам параметров:

 String& MyClass::doSomething();
 String& MyClass::doSomething() const;

может мыслиться примерно так:

 String& MyClass_doSomething(MyClass *this);
 String& MyClass_doSomething(const MyClass *this);

Что касается полезности этого, простейшими примерами являются методы begin и end в различных контейнерах std::. Если vector / string / что-либо не является константным, и вы звоните begin(), вы получите обратно iterator, который можно использовать для изменения содержимого исходного контейнера. Очевидно, что это не должно быть разрешено для контейнеров, помеченных const, поэтому, благодаря перегрузке const / non const, вызов begin() для вектора const возвращает const_iterator, который может использоваться для чтения содержимого вектора , но не изменять его.

, например

string nc = "Hello world";
for (string::iterator iString = nc.begin(); iString != nc.end(); ++iString)
{
    cout << *iString;; // legal to read
    *iString = toupper(*iString); // legal to write

}

const string c = "Hello world again";
for (string::const_iterator iString = c.begin(); iString != c.end(); ++iString)
{
    cout << *iString;; // legal to read
    // *iString = toupper(*iString);  // Writing is illegal
}

Что касается перегрузки по типу возвращаемого значения, вы не можете сделать это в C ++. Тем не менее, вы можете моделировать его довольно прилично.

2 голосов
/ 17 июня 2010

Так используется итератор. У вас есть как постоянный, так и неконстантный.

2 голосов
/ 17 июня 2010

Да, вы можете сделать это. (@Job, это не перегрузка для возвращаемого типа, это перегрузка для 'const-state' экземпляра вызываемого класса)

Если экземпляр const, будет вызван второй вариант, если нет, будет вызван первый вариант. Практическое использование заключается в том, что если метод вызывается для экземпляра const, вы, вероятно, также захотите вернуть «const String &» (например, если вы возвращаете ссылку на член класса), например, так:

//function which can modify member
String& MyClass::doSomething();

//constant member function
const String& MyClass::doSomething() const;
1 голос
/ 17 июня 2010

Это не только возможно, но и часто используется.

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

...