2013-02-15 3 views
15

Составитель:г ++ 4.7.2параметры по умолчанию в .h и .cpp файлов

Ok. Поэтому я смущен параметрами по умолчанию в файлах .h и .cpp. Во многих местах (включая этот сайт) упоминается, что параметры по умолчанию могут быть добавлены только в .h-файлах, а не в .cpp-файлах. Однако этот код доказывает, что это не так:

test1.h

#pragma once 

#include <iostream> 
using namespace std; 

class Class{ 
public: 
    Class(int, int, int=1); 
}; 

test1.cpp

#include "test1.h" 

Class::Class(int a, int b=2, int c) 
{ 
    cout<<a<<" "<<b<<" "<<c<<endl; 
} 

int main() 
{ 
    Class a(1); 
    return 0; 
} 

Теперь, согласно тому, что я испытал, параметры по умолчанию могут быть добавлено к .cpp файлам. Однако следующие ограничения имеют место

  1. параметры по умолчанию, присутствующие в .cpp и .h файл не должен перекрытия. то есть Class(a, b, c=1) (в файле .h) и Class::Class(a,b,c=2) (в .cpp-файле) является недопустимым.

    Хорошо известно, что после того, как параметры по умолчанию были добавлены , все переменные, объявленные после этого, также должны содержать значения по умолчанию. Позволяет называть это правило defpara. Теперь,

  2. Переменные, указанные в объявлении функции (.h файла) должны подчиняться defpara правила т.е. Class(a, b=2, c) (в файле .h) является недействительными независимо от того, что объявленных в .cpp файл.

  3. Если рассматривать переменные, имеющие значения по умолчанию (как пересечения значений по умолчанию в .h и .cpp файлах), было бы следовать defpara правила. то есть Class(a, b, c=1) (в файле .h) и Class::Class(a,b=2,c) (в файле .cpp). Но Class(a, b, c=1) (в .h файле) и Class::Class(a=2,b,c) (в файле .cpp) является недействительным.

Итак .... Я прав, неправильно ???

ответ

14

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

Еще один способ взглянуть на это, когда какой-то другой включает в себя test.h, все, что видит код, это то, что объявлено в test.h, поэтому аргументы по умолчанию, помещенные в другое место, не будут использоваться.

32

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

Это связано с тем, что компилятор будет использовать заголовочный файл для ВСЕХ компиляторов, которые используют ваш класс [если вы не являетесь «непослушными» и не должны использовать файл заголовка везде, куда он должен идти].

Поскольку компилятор добавляет аргументы по умолчанию, когда компилирует код, который ВЫЗЫВАЕТ функцию (в данном случае конструктор), не имеет значения, какие значения по умолчанию находятся в файле .cpp.

Конечно, в этом случае есть только один «пользователь» файла заголовка и только одно место, где вызывается конструктор. Но наличие значений по умолчанию в файле .cpp обычно неверно [если это не локальная функция].

Вы получаете очень «интересные» ошибки, если вы «смешиваете» значения по умолчанию - например. если ваш .cpp имеет один по умолчанию, а headefile - другой. Если вы действительно умеете, вы даже можете заставить компилятор генерировать разные значения по умолчанию для разных вызовов функции, что почти наверняка приведет к некоторому сбору в работе, если код полагается на значение по умолчанию определенного значения. И не испытывайте соблазна скопировать значения по умолчанию из заголовка в .cpp-файл «просто, чтобы было легче увидеть». Если кто-то изменит значение по умолчанию, то он почти наверняка либо не изменится в обоих местах, а, возможно, еще хуже: измените неправильные значения по умолчанию, чтобы он не делал то, что предназначалось.

+0

Означает ли это, в определении метода в cpp file, нет необходимости писать значение по умолчанию? – laike9m

+1

Да, вы не должны иметь его дважды, а заголовочный файл - там, где он принадлежит. –

2

Не существует такого параметра, как параметр по умолчанию для определения файла на C++ - он существует только в объявлении.

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

PS: Пункт 38/Скотт Майерс/Эффективный C++ - Никогда не переопределяйте унаследованное значение параметра по умолчанию.

+0

Малый: в 3-м издании это товар # 37 (определенно стоит прочитать) – nmarler

5

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

void f(int, int = 3); 
void f(int, int = 3); // error: redefinition of default argument 

Однако последующие заявления могут добавлять аргументы по умолчанию:

void f(int, int = 3); 
void f(int = 4, int = 3); 
f(); // calls f(4, 3); 

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

void f(int, int =3); 
f(1); // calls f(1, 3); 
void f(int = 4, int = 3); 
f(1); // calls f(1, 3); 
f(); // calls f(4, 3); 

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

Class c3(1, 2, 3); 
Class c2(1, 2); 

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

Class c3(1, 2, 3); 
class c2(1, 2); 
class c1(1); 
Смежные вопросы