2013-02-15 31 views
15

biên dịch:g ++ 4.7.2thông số mặc định trong file .h và .cpp

Ok. Vì vậy, tôi bối rối về các tham số mặc định trong các tệp .h.cpp. Nó được đề cập ở nhiều nơi (bao gồm cả trang web này) rằng các tham số mặc định có thể được thêm vào chỉ trong các tệp .h và không có trong tệp .cpp. Tuy nhiên, mã này đã chứng minh nó sai:

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; 
} 

Bây giờ, theo những gì tôi đã thử nghiệm, các thông số mặc định có thể được thêm vào .cpp tệp. Tuy nhiên, những hạn chế sau giữ:

  1. Các thông số mặc định có mặt trong .cpp.h tập tin không nên chồng chéo. tức là Class(a, b, c=1) (trong tệp .h) và Class::Class(a,b,c=2) (trong tệp .cpp) không hợp lệ.

    Đó là quy tắc nổi tiếng khi các tham số mặc định đã được thêm , tất cả các biến được khai báo sau đó cũng phải chứa giá trị mặc định. Cho phép gọi đây là quy tắc defpara. Bây giờ,

  2. Các biến được nêu trong phần khai báo hàm (.h tập tin) nên tuân theo defpara rule ví dụ Class(a, b=2, c) (trong file .h) là không hợp lệ không phụ thuộc vào những gì đang khai báo trong tập tin cpp.

  3. Nếu ta xem xét các biến có giá trị mặc định (như là một ngã tư các giá trị mặc định trong .h.cpp files), nó sẽ theo defpara quy tắc. tức là Class(a, b, c=1) (trong tệp .h) và Class::Class(a,b=2,c) (trong .cpp tệp) hợp lệ. Nhưng Class(a, b, c=1) (trong tệp .h) và Class::Class(a=2,b,c) (trong .cpp tệp) là không hợp lệ.

Vì vậy .... Tôi đúng, sai ???

Trả lời

14

Điều này chỉ hoạt động vì chức năng chính của bạn cũng nằm trong tệp test.cpp của bạn, do đó, nó thấy đối số mặc định được chỉ định trong triển khai lớp của bạn. Nếu bạn đặt hàm main vào một tệp riêng biệt chỉ bao gồm test.h, mã này sẽ không biên dịch.

Một cách khác để xem xét là, khi một số khác bao gồm test.h, tất cả mã đó xem là những gì được khai báo trong test.h, vì vậy đối số mặc định được đặt ở nơi khác sẽ không được sử dụng.

32

Giá trị mặc định phải luôn ở trong tệp tiêu đề, nếu hàm được khai báo trong tệp tiêu đề.

Điều này là do trình biên dịch sẽ sử dụng tệp tiêu đề cho tất cả các đơn vị biên dịch sử dụng lớp của bạn [trừ khi bạn đang "nghịch ngợm" và không sử dụng tệp tiêu đề ở mọi nơi cần đi].

Vì trình biên dịch thêm đối số mặc định khi biên dịch mã GỌI hàm (trong trường hợp này hàm khởi tạo), nó không quan trọng những gì mặc định nằm trong tệp .cpp.

Tất nhiên, trong trường hợp này, chỉ có một "người dùng" của tệp headerfile và chỉ một nơi mà hàm tạo được gọi. Nhưng có mặc định trong tập tin .cpp nói chung là sai [trừ khi nó là một hàm cục bộ].

Bạn nhận được các lỗi rất "thú vị" nếu bạn "kết hợp" mặc định - ví dụ: nếu tệp .cpp của bạn có một giá trị mặc định và headfile là một giá trị khác. Nếu bạn thực sự có kỹ năng, bạn thậm chí có thể nhận được trình biên dịch để tạo ra các giá trị mặc định khác nhau cho các cuộc gọi khác nhau đến hàm, mà gần như chắc chắn sẽ dẫn đến một số headscratching nếu mã dựa trên mặc định là một số giá trị cụ thể. Và đừng bị cám dỗ để sao chép các giá trị mặc định từ tiêu đề sang tệp .cpp "chỉ để làm cho việc xem dễ dàng hơn". Nếu ai đó thay đổi mặc định, thì gần như chắc chắn sẽ không thay đổi ở cả hai nơi và có thể tệ hơn: thay đổi mặc định sai, vì vậy nó không làm những gì được dự định.

+0

Liệu nó có nghĩa trong định nghĩa phương pháp trong cpp tập tin, không cần phải viết giá trị mặc định? – laike9m

+1

Có, bạn không nên có nó hai lần, và tập tin tiêu đề là nơi nó thuộc về. –

2

Không có tham số mặc định cho định nghĩa tệp trong C++ - nó chỉ tồn tại trong khai báo.

Điều gì xảy ra là trình biên dịch thấy chức năng thiếu thông số sau. Nếu chúng là mặc định, nó có thể điền vào các khoảng trống để xây dựng mã đối tượng để gọi hàm như thể hàm gọi có các tham số đó.

PS: Mục 38/Scott Myers/Hiệu quả C++ - Không bao giờ xác định lại giá trị thông số mặc định được kế thừa.

+0

Nhỏ: trong ấn bản thứ 3, nó là Item # 37 (chắc chắn đáng đọc) – nmarler

5

.h vs. .cpp là cá trích đỏ. Quy tắc là các đối số mặc định có thể được sử dụng trong các khai báo hàm và trong định nghĩa của hàm. Bạn không được phép xác định lại một đối số mặc định, thậm chí không cho cùng một giá trị. Vì vậy, đây không phải là quy phạm pháp luật:

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

Tuy nhiên, tuyên bố tiếp theo có thể thêm đối số mặc định:

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

Hơn nữa, tại bất kỳ điểm mà hàm được gọi, các đối số mặc định mà đã được nhìn thấy tại thời điểm đó có thể được sử dụng:

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); 

Ví dụ ban đầu, tệp .h xác định một đối số mặc định và bất kỳ đơn vị dịch nào sử dụng tiêu đề đó có thể sử dụng đối số mặc định đó:

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

Hơn nữa, các tập tin cpp định nghĩa một đối số mặc định bổ sung, vì vậy sau khi tuyên bố rằng các nhà xây dựng có thể được gọi với một, hai, hoặc ba đối số:

Class c3(1, 2, 3); 
class c2(1, 2); 
class c1(1); 
Các vấn đề liên quan