2014-09-08 13 views
12

Właśnie zaczynam uczyć C++, pochodzących z innych języków. Żałuję, że nie było sposobu, aby konsekwentnie sprawdzać API stworzone przez plik (studenta).Poczytalność nagłówków

Załóżmy student podnosi tego pliku:

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

Właściwie przypuszczać spytałem studenta zdefiniować jakąś inną funkcję int x (int). Chciałbym móc to sprawdzić uruchamiając ten kod:

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

Więc staram się zobaczyć, czy wdrożenie studenta dopasowany odpowiedni interfejs i testowania go na wejście 0. Chciałbym mieć nadzieję, nie byłoby skompilować. Ale kiedy zrobić

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

To kompiluje i działa bez zarzutu, dając wyjście 0. To pozostaje prawdą, nawet jeśli skompilować dwa pliki osobno i połączyć je później.

Wiem, że nm nie wyświetla typów zwrotu. Czy to jest ten sam powód, dla którego możemy połączyć dwa pliki, gdy wartości zwracane nie są zgodne? Czy istnieje jakiś rozsądny sposób na sprawdzenie tego? (Podobnie jak w przypadku twierdzeń typu kompilacji?)

Czy jest to konkretny błąd z powodu int i double being interconvertible? Czy są dostępne dodatkowe opcje kompilatora, które mogłyby to złapać?

+3

Pojawiłby się błąd, gdyby słowo "stu.cpp" zawierało słowo "stu.h". –

+2

Tak, powinieneś skompilować z '-Wall -Werror -Wextra' i dać uczniom plik nagłówkowy do implementacji (który będzie obejmował' # include'-inging). –

+0

Możesz spróbować z 'g ++ -flto -Wall -Wconversion * .cpp -o gra' –

Odpowiedz

8

Zamiast kompilować kod ucznia osobno, dlaczego nie umieścisz go bezpośrednio w programie testera?

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

Następnie należy uzyskać ładny błąd tak:

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

Choć nie jest to „normalny” sposób kompilacji kodu ucznia, to gwarantuje, że kod może zostać sprawdzona.


Alternatywnie, można użyć opcji kompilatora wiersza polecenia jak -include (GCC), dzyń zmusić kompilator, aby dołączyć plik nagłówka zawierającego żądany API podczas kompilacji C++ plik studenta. Jako przykład:

api.h

int x(int); 

skompilować z g++ stu.cpp -include api.h, i odpowiedni błąd zostanie podniesiony.

+1

Może to prowadzić do fałszywych alarmów, takich jak redefinicja symbolu. –

+0

@OliCharlesworth: Dlaczego? Pierwsze rozwiązanie transkoduje 'stu.cpp', więc' stu.cpp' nie zostałoby niezależnie skompilowane. Drugie rozwiązanie wprowadza tylko nagłówek wybranego sortownika, który powinien zawierać tylko prototypy funkcji. Nie widzę, gdzie mogłyby wystąpić błędy redefinicji symboli? – nneonneo

+0

Była jeszcze jedna odpowiedź, teraz usunięta, za pomocą wskaźników funkcyjnych, które były dość eleganckie, zwłaszcza, że ​​ułatwiłoby to również sprawdzenie, kiedy student pomija metodę definiowania. Przy takim podejściu istnieje sposób na podniesienie błędu, jeśli metoda nigdy nie została zdefiniowana? Obawiam się, że "po prostu próba wywołania tego" nie zawsze będzie działać, ponieważ C++ automagicznie przekształci wiele typów za kulisami. – daveagp

1

można wykonać następujące czynności:

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

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

i skompilować tylko gra.cpp oczywiście.