function — установка параметров по умолчанию в переполнении стека

У меня есть небольшой вопрос о том, как значения по умолчанию задаются для параметров функции в C ++. Проблема, с которой я столкнулся, возможно, связана с моим непониманием того, где параметры должны быть объявлены / определены в прототипе функции или в заголовке функции, или в обоих случаях? Коды ниже с отмеченными ошибками:

#include <iostream>

using namespace std;

float volume(float l, float w, float h);

int main() {

float length;
float width;
float height;

cout << volume() << endl; // Here, with 'volume()' underlined, it says:
//no matching function for call to 'volume()'

cout << "Length: ";
cin >> length;

cout << "Width: ";
cin >> width;

cout << "Height: ";
cin >> height;

cout << "Volume = " << volume(length, width, height) << endl;}

float volume(float l = 1, float w = 1, float h = 1){

float vol = l * w * h;

return vol;
}

В другой попытке вот что произошло:

#include <iostream>

using namespace std;

float volume(float l = 1, float w = 1, float h = 1);

int main() {

float length;
float width;
float height;

cout << volume() << endl;

cout << "Length: ";
cin >> length;

cout << "Width: ";
cin >> width;

cout << "Height: ";
cin >> height;

cout << "Volume = " << volume(length, width, height) << endl;}

float volume(float l = 1, float w = 1, float h = 1){ //Here, Xcode says that
// that the error is: Redefinition of default argument. < which I believe I understand.

float vol = l * w * h;

return vol;
}

В моей последней попытке, которая сработала, я сделал это:

#include <iostream>

using namespace std;

float volume(float l = 1, float w = 1, float h = 1);

int main() {

float length;
float width;
float height;

cout << volume() << endl;

cout << "Length: ";
cin >> length;

cout << "Width: ";
cin >> width;

cout << "Height: ";
cin >> height;

cout << "Volume = " << volume(length, width, height) << endl;}

float volume(float l, float w, float h){

float vol = l * w * h;

return vol;
}

Может ли кто-нибудь объяснить мне логику, почему последний работал, а первые два — нет? Есть ли другой способ, которым код все еще будет работать таким же образом с параметрами, указанными в другом месте, или значениями по умолчанию, установленными в другом месте? Существуют ли какие-либо соглашения или более предпочтительные практики в этой области?

Адам

0

Решение

C ++ и C анализируются сверху вниз. Когда компилятор интерпретирует утверждение, он не знает о вещах, которые еще не прочитал.

В вашем первом примере вы объявляете функцию с именем «volume», которая в качестве прототипа принимает 3 float и возвращает float. Затем вы пытаетесь вызвать функцию с именем «volume», которая не принимает параметров, которых еще нет (это будет другая функция, поскольку C ++ поддерживает полиморфизм). Позже вы определяете функцию, которая может принимать 0, 1, 2 или 3 числа с плавающей запятой, но это слишком поздно и имеет несовместимый прототип с первым.

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

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

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

1

Другие решения

Добавление к ответу выше от Бьярне Страуструп

Аргумент по умолчанию — это тип, проверяемый во время объявления функции и оцениваемый во время вызова. Аргументы по умолчанию могут быть предоставлены только для конечных аргументов. Например:

int f (int, int = 0, char * = 0); // Хорошо

int g (int = 0, int = 0, char *); // ошибка

int h (int = 0, int, char * = 0); // ошибка

Аргумент по умолчанию может быть повторен в последующем объявлении в той же области, но не изменен.
Например:

пустота f (int x = 7);

пустота f (int = 7); // Хорошо

пустота f (int = 8); // ошибка: разные аргументы по умолчанию

void g () {void f (int x = 9); // хорошо: это объявление скрывает внешнее}

Объявление имени во вложенной области видимости так, что имя скрывает объявление с тем же именем во внешней области, подвержено ошибкам.

0

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

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

void f(int);

int main() {
f(3); // argument should specified.

void f(int = 1);
f(); // calls f(1)
}

void f(int n = 2) {
}

void g() {
f(); // calls f(2)
}

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

0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector