Wątek zablokowany 2018-12-13 13:34 przez furious programming.

Dyrektywa #ifndef – wyjaśnienie sensu jej używania w specyficzny sposób

0

Witam, czy mógłby mi ktoś napisać po co używa się dyrektywy #ifndef w taki sposób:

#ifndef _NazwaPliku_H_
#define _NazwaPliku_H_

jeśli nigdzie dalej nie jest to w żaden sposób wykorzystywane?
Takie użycie jest w pliku z końcówką .h

1

Bo każde #include powoduje wklejenie zawartości pliku dołączanego do tego pliku gdzie jest include. W efekcie mogłoby się zdarzyć ze jakiś plik jest includowany dwa razy w tym samym pliku źródłowym i pojawiłby się problem, bo masz na przykład dwie definicje tej samej klasy. To co pokazałeś to jest tzw strażnik nagłówka który przed tym zabezpiecza.

2

wyobraź sobie plik NazwaPliku.h o takiej właśnie treści:

#ifndef _NazwaPliku_H_
#define _NazwaPliku_H_
void foo();
#endif _NazwaPliku_H_

a potem plik Program.c o takiej treści:

#include "NazwaPliku.h"
#include "NazwaPliku.h"

gdyby nie było strażników, plik nagłówkowy wklejony by został dwa razy:

void foo();
void foo();

co tu może nie zaszkodzi, ale czasami jest to zdecydowanie nie na rękę.

Jednak dzięki ifdefom, rozwija się to do

#ifndef _NazwaPliku_H_
#define _NazwaPliku_H_
void foo();
#endif _NazwaPliku_H_

#ifndef _NazwaPliku_H_
#define _NazwaPliku_H_
void foo();
#endif _NazwaPliku_H_

co po rozwiązaniu dyrektyw daje

#define _NazwaPliku_H_
void foo();

i mamy treść pliku .h wklejoną tylko raz.

Czasami nie możemy zapobiec wielokrotnemu inkludowaniu tego samego nagłówka, albo za dużo zachodu by to wymagało — a dzięki tej sztuczce mamy problem z głowy.

0

Uuu, czytałem o tym i niestety źle to zinterpretowałem. Masz rację! już to rozumiem :)
Dzięki

0

Witam. Wiem, że odświeżam wątek z 2012, ale moim zdaniem nie ma sensu zakładać oddzielnie nowego tematu, bo mam tylko jedno pytanie odnośnie dzielenia kodu na kilka plików, a powyżej już część została wytłumaczona. Mam takie pliki:

  1. plik z funkcja main
//Plik: main.cpp
#include <iostream>
#include <conio.h>

#include "nazwaPliku.hpp"

using namespace std;
int main()
{
    cout << "Wynik dodawania to: " << dodajLiczby( 10, 15 ) << endl;
    getch();
    return( 0 );
}
  1. plik nagłówkowy
//#ifndef nazwaPliku_hpp
//#define nazwaPliku_hpp

int dodajLiczby( int a, int b );

//#endif
  1. plik wykonywalny
//Plik: nazwaPliku.cpp
#include "nazwaPliku.hpp"

int dodajLiczby( int a, int b )
{
    return( a + b );
}

Jak widzicie, instrukcje #ifndef i #endif umieściłem w komentarz, czyli tak naprawdę usunąłem je z kodu, a mimo to program się kompiluje i działa, nawet jeżeli w pliku głównym dwa razy wpiszę
#include "nazwaPliku.hpp". Dlaczego?

0

Bo masz szczęście i akurat przy redefinicji redeklaracji nic nie wybucha. W ogólności może jednak tak nie być.

1
Althorion napisał(a):

Bo masz szczęście i akurat przy redefinicji nic nie wybucha. W ogólności może jednak tak nie być.

Przy redefinicji właśnie wybucha. :) @kario97 ma deklaracje, a deklaracje mogą się powtarzać. int dodajLiczby( int a, int b ); jest deklaracją.

0
koszalek-opalek napisał(a):
Althorion napisał(a):

Bo masz szczęście i akurat przy redefinicji nic nie wybucha. W ogólności może jednak tak nie być.

Przy redefinicji właśnie wybucha. :) @kario97 ma deklaracje, a deklaracje mogą się powtarzać. int dodajLiczby( int a, int b ); jest deklaracją.

Hmm, a mógłbyś zmodyfikować ten program tak, aby nadal był prosty jak budowa cepa i jednocześnie "wybuchł"? xd

0

@kario97: Dopisz w pliku nagłówkowym jakąś zmienną globalną, na przykład int liczba; (bo to już jest definicja a nie deklaracja) i już chyba będzie źle.

PS. Oczywiście zmiennych globalnych nie wolno używać. :)

0

Zmieniłem na coś takiego:

#ifndef nazwaPliku_hpp
#define nazwaPliku_hpp

int liczba;
int dodajLiczby( int a, int b );

#endif

Jak widzisz tym razem są już instrukcje ifndef i endif, ale program i tak się nie kompiluje. xD

0

Kompiluje się u mnie (bo wyrzuceniu conio i getch), może u Ciebie się nie linkuje, bo masz złe ustawienia projektu...? Jakie dostajesz komunikaty?

A, nie linkuje się teraz przez tę liczbę... :) Zaraz pomyślę nad inną "poprawką". :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1