2014-09-08 18 views
12

Tôi mới bắt đầu dạy C++, đến từ một số ngôn ngữ khác. Tôi muốn có một số cách để kiểm tra liên tục API được tạo bởi một tệp (học sinh).Sanity of Headers

Giả sử một sinh viên nộp hồ sơ này:

// this is stu.cpp 
#include <iostream> 
using namespace std; 
double x(int y) {return y+0.5;} 

Trên thực tế, giả sử tôi hỏi học sinh để xác định một số chức năng khác int x (int). Tôi muốn để có thể kiểm tra điều này bằng cách chạy mã này:

// this is stu.h 
int x(int); 

// this is gra.cpp 
#include "stu.h" 
#include <iostream> 
using namespace std; 

int main() { 
    cout << x(0); // test their code 
} 

Vì vậy, tôi đang cố gắng để xem nếu thực hiện của học sinh phù hợp với giao diện yêu cầu, và thử nghiệm nó trên đầu vào 0. Tôi đã có thể hy vọng điều này sẽ không biên dịch. Nhưng khi tôi làm

g++ -Wall -Wconversion *.cpp -o gra 
./gra 

Nó biên dịch và chạy mà không bị rơi, cho đầu ra 0. Điều này vẫn đúng ngay cả khi tôi biên dịch hai tệp một cách riêng biệt và liên kết chúng sau.

Tôi biết rằng nm không liệt kê các loại trả lại. Có phải đó là lý do tương tự mà chúng tôi có thể liên kết với nhau hai tệp khi giá trị trả lại không khớp không? Có cách nào lành mạnh để kiểm tra điều này không? (Giống như có các xác nhận kiểu thời gian biên dịch không?)

Hoặc đây có phải là lỗi cụ thể do int và double có thể chuyển đổi được không? Có các tùy chọn trình biên dịch bổ sung có thể bắt được điều này không?

+3

Bạn sẽ gặp lỗi nếu 'stu.cpp' bao gồm' stu.h'. –

+2

Yup, bạn nên biên dịch với '-Wall -Werror -Wextra' và cung cấp cho sinh viên tệp tiêu đề để triển khai (sẽ liên quan đến' # include'-ing nó). –

+0

Bạn có thể thử với 'g ++ -flto -Wall -Wconversion * .cpp -o gra' –

Trả lời

8

Thay vì biên dịch mã của học sinh một cách riêng biệt, tại sao bạn không chỉ đưa mã trực tiếp vào chương trình người thử nghiệm của mình?

int x(int); 
#include <stu.cpp> 

Sau đó, bạn sẽ nhận được một lỗi đẹp như thế này:

a.cpp:2:8: error: functions that differ only in their return type cannot be overloaded 

Trong khi đây không phải là "bình thường" cách để biên dịch mã của một học sinh, nó đảm bảo rằng mã có thể được kiểm tra.


Ngoài ra, bạn có thể sử dụng tùy chọn trình biên dịch dòng lệnh như -include (GCC, Clang) để buộc các trình biên dịch để bao gồm một tập tin header chứa API của bạn mong muốn khi biên dịch C++ hồ sơ của học sinh. Như một ví dụ:

api.h

int x(int); 

biên dịch với g++ stu.cpp -include api.h, và lỗi thích hợp sẽ được nâng lên.

+1

Nó có thể dẫn đến sai tích cực mặc dù, chẳng hạn như định nghĩa lại biểu tượng. –

+0

@OliCharlesworth: Tại sao? Giải pháp đầu tiên transcludes 'stu.cpp', do đó,' stu.cpp' sẽ không được biên dịch độc lập. Giải pháp thứ hai chỉ tiêm một tiêu đề của sự lựa chọn của học sinh, mà chỉ nên chứa các nguyên mẫu hàm. Tôi không thấy các lỗi định nghĩa lại biểu tượng sẽ xảy ra ở đâu? – nneonneo

+0

Có một câu trả lời khác, bây giờ đã bị xóa, sử dụng các con trỏ hàm khá thanh lịch, đặc biệt vì nó cũng sẽ giúp bạn dễ dàng kiểm tra khi một học sinh bị bỏ qua định nghĩa phương thức. Với cách tiếp cận này, có cách nào để nêu ra một lỗi nếu phương pháp này chưa bao giờ được xác định? Tôi lo ngại rằng "chỉ cần thử gọi nó" sẽ không luôn luôn làm việc kể từ khi C + + sẽ tự động chuyển đổi rất nhiều loại đằng sau hậu trường. – daveagp

1

Bạn có thể làm như sau:

// this is gra.cpp 
#include "stu.h" 
#include "stu.cpp" 
#include <iostream> 
using namespace std; 

int main() { 
    cout << x(0); // test their code 
} 

Và biên dịch chỉ gra.cpp tất nhiên.