const ключова позиція в оголошенні функції

Можливі дублікати :
   Різниця між деклараціями const у C ++

#include 

class Bar{};

void foo(const Bar x){}  //l5
void foo(Bar x){}        //l6
void foo(Bar const x){}  //l7

////pointer functions

void foo(const Bar* x){} //l11
void foo(Bar* x){}       //l12
void foo(Bar* const x){} //l13

Висновок компілятора: (довгий короткий l5 , l6 , конфлікт l7 конфлікт)

untitled.cpp:6:6: error: redefinition of ‘void foo(Bar)’
untitled.cpp:5:6: error: ‘void foo(Bar)’ previously defined here
untitled.cpp:7:6: error: redefinition of ‘void foo(Bar)’
untitled.cpp:5:6: error: ‘void foo(Bar)’ previously defined here
untitled.cpp:13:6: error: redefinition of ‘void foo(Bar*)’
untitled.cpp:12:6: error: ‘void foo(Bar*)’ previously defined here

Що відбувається?

  1. Яке значення має кожна з оголошень
  2. Чому всі 3 декларації конфліктують з функціями об'єкта, але тільки 2 з функціями покажчика?
  3. Будь ласка, поясніть, що конфлікт знаходиться між l12 та l13 , навіть якщо l12 не містить ключового слова const /li>
  4. На жаль, якщо тривіальне запитання
7

6 Відповіді

"Проблемою" є те, що const ness значення параметра не бере участь у перевантаженні!

По-перше, Бар const і const Bar вже є ідентичним значенням, тому вони автоматично матимуть проблему. Але як параметр функції const не поширюється на перевантаження, тому версія Bar також виглядає те ж саме. Параметр const у пареметре вказує компілятору, що ви не збираєтеся змінювати його у тілі функції.

З тієї ж причини, Бар * і Бар * const обробляються однаково: const застосовується до значення параметра (не вказано до) і не бере участь у перевантаженні, тому ви визначили ту ж саму функцію.

З іншого боку const Bar * означає щось зовсім інше: неконстантний покажчик на об'єкт const (типу Бар ). Оскільки тип відрізняється, він бере участь у перевантаженні і дозволяє цій функції бути унікальною.

5
додано

В основному, оскільки C ++ копіює значення при виклику функції, немає нічого, щоб відрізнити перші три від точки зору. (Абонент знає, що функція не може змінити своє власне значення, яке він передає, тому кожен параметр функції неявно постійний у багатьох відношеннях, з точки зору абонента в будь-якому випадку).

Коли ви говорите про покажчики, однак, якщо ви передаєте вказівник на константу проти покажчика на неконстантну, є відмінність для абонента (один не змінить ваші речі, інший може). Ось чому l11 і l12 не конфліктують.

l12 і l13 конфлікт, хоча, тому що вони обидві покажчики на Бар * (один є константним покажчиком, один не є, так само проблема, як l5-l7, немає ніякої різниці для абонента).

Ця остання точка може бути трохи складнішою - зауважте, що int const * a те саме, що і const int * a , ці не те ж, що і int * const a , перші два є покажчиками на константу int, інша - на постійний покажчик на int (тобто значення вказівника не може змінитися в пізнішому).

1
додано

Не має значення, чи буде ви ставити const до або після імені типу.

15 і 17 мають однаковий список аргументів параметрів Ці 2 функції мають однаковий прототип і є дублікатами.

Функція №1

void foo(const int x) {
return;
}

Функція # 2 - Дублювати список параметрів параметрів

void foo( int const x) {
return;
}

Положення const є таким же, як 15 і 17 у наведеному прикладі.

Або буде працювати відповідно до Вікіпедії:

http://en.wikipedia.org/wiki/Const-correctness

1
додано
Повторіть перше речення: це не має значення для компілятора, в даному конкретному контексті. Однак, як правило, const змінює те, що передує йому, і систематично встановлює const після того, що він змінює (тобто int const , а не const int ) робить код більш читабельним.
додано Автор James Kanze, джерело
void foo(const Bar x){}
void foo(Bar const x){}

Дві вищезгадані ідентичні, тому що обидва слова x мають тип Бар і це const .

void foo(Bar x){}

Це конфліктує з вищезазначеним 2, оскільки x const чи ні, це деталь реалізації вашої функції, і відкидається компілятором підпис функції. Отже, всі три функції мають той самий підпис, який є void foo (Bar x) .

void foo(Bar* x){}
void foo(Bar* const x){}

Це схоже на попередній випадок; ви вказуєте, що покажчик x const , тобто ви не будете повторно вказувати x на щось інше у вашій функції. В обох випадках об'єкт Bar , на який вказує x , не є const . Таким чином, const ness x є деталлю реалізації функції.

void foo(const Bar* x){}

Тут ви вказуєте, що x вказує на бар , який є const . Це відрізняється від попередніх 2 випадків, тому конфлікту немає.

0
додано

Причина, по якій перші три створюють конфлікт, полягає в тому, що компілятор не може визначити, яку функцію використовувати в будь-якому випадку. При виклику foo (BarObject); компілятор може дуже добре використовувати будь-який з них, чи був оголошений BarObject const чи ні.

Однак на тих, що мають параметри як покажчики, коли ви викликаєте foo (BarPointer); , якщо BarPointer було оголошено як const Bar * BarPointer; буде вибирати ] 11 , оскільки він гарантує, що вказаний об'єкт не буде змінений у функції (не у випадку передачі за значенням, як у перших трьох). Якщо вона не є const , вона не знає, чи повинна вона викликати ] 12 або ] 13 , оскільки Bar * const x означає, " x не може вказувати ні на що інше, ніж на те, що було передано як параметр", і це не стосується абонента.

Невелика посилання на декларації:

const Bar x//x is an immutable copy of the original parameter.
Bar const x//same as above and gets compiled, but cdecl says it is a syntax error.

const Bar* x//x points to an object that can't be changed.
Bar* const x//x can't point to any other object than the parameter passed.
0
додано

Для перших трьох функцій - const не має значення про перевантаження роздільної здатності у випадку, коли змінна передається значенням . Копія аргументу, створеного на стеку, і не має сенсу, якщо ця копія змінюється або не з зовнішньої точки зору. Це має значення для самої функції (всередині).

Для другого випадку, функції на основі покажчика, це важлива частина роздільної здатності функції, оскільки копії не створюються на стеку, а з точки зору зовнішньої (викликає) точки зору це означає, що функція буде змінювати значення аргументу.

Для двох останніх функцій вкажіть компілятору: вказівник x на Бар , а значення Бар вказано x Я можу змінити. Але в першому випадку ви можете змінити значення покажчика x (наприклад, вказати іншу панель Bar ) навпроти другого випадку. І тут ми знаходимося в першій ситуації - копії покажчиків самі стоять на стеку, і немає сенсу перевантажувати роздільну здатність, якщо вони змінюються всередині функції чи ні.

0
додано
IT KPI C/С++ новым годом
IT KPI C/С++ новым годом
747 учасників

Чат обсуждения С/С++. - Вопросы "напишите за меня лабу" - это оффтоп. - Оффтоп, флуд, оскорбления и вбросы здесь не приняты. - За нарушение - предупреждение или mute на неделю. - За спам и рекламу - ban. Все чаты IT KPI: https://t.me/itkpi/1147