Archief - [PROG][C++] Header bestanden

Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.

MacK

Legacy Member
In mijn cpp-boek zat volgend voorbeeld om het gebruik van namespaces te illustreren. Nu valt mij op dat die header file (namesp.h) zo geen #ifndef _NAMESP_H_
#define ... (je weet wel wat ik bedoel)

bevat. Ik heb het op beide manieren eens gecompiled, en dat werkt bij beide. Kan iemand me het verschil uitleggen?

Code:
// namesp.h
// create the pers and debts namespaces
namespace pers
{
    const int LEN = 40;
    struct Person
    {
        char fname[LEN];
        char lname[LEN];
    };
    void getPerson(Person &);
    void showPerson(const Person &);
}

namespace debts
{
    using namespace pers;
    struct Debt
    {
        Person name;
        double amount;
    };

    void getDebt(Debt &);
    void showDebt(const Debt &);
    double sumDebts(const Debt ar[], int n);
}
Code:
// usenmsp.cpp -- using namespaces
#include <iostream>
#include "namesp.h"

void other(void);
void another(void);
int main(void)
{
    using debts::Debt;
    using debts::showDebt;
    Debt golf = { {"Benny", "Goatsniff"}, 120.0 };
    showDebt(golf);
    other();
    another();
    
    return 0;
}

void other(void)
{
    using std::cout;
    using std::endl;
    using namespace debts;
    Person dg = {"Doodles", "Glister"};
    showPerson(dg);
    cout << endl;
    Debt zippy[3];
    int i;
    
    for (i = 0; i < 3; i++)
        getDebt(zippy[i]);

    for (i = 0; i < 3; i++)
        showDebt(zippy[i]);
    cout << "Total debt: $" << sumDebts(zippy, 3) << endl;
    
    return;
}

void another(void)
{
    using pers::Person;;
    
    Person collector = { "Milo", "Rightshift" };
    pers::showPerson(collector);
    std::cout << std::endl; 
}
Code:
// namesp.cpp -- namespaces
#include <iostream>
#include "namesp.h"

namespace pers
{
    using std::cout;
    using std::cin;
    void getPerson(Person & rp)
    {
        cout << "Enter first name: ";
        cin >> rp.fname;
        cout << "Enter last name: ";
        cin >> rp.lname;
    }
    
    void showPerson(const Person & rp)
    {
        std::cout << rp.lname << ", " << rp.fname;
    }
}

namespace debts
{
    void getDebt(Debt & rd)
    {
        getPerson(rd.name);
        std::cout << "Enter debt: ";
        std::cin >> rd.amount;
    }
    
    void showDebt(const Debt & rd)
    {
        showPerson(rd.name);
        std::cout <<": $" << rd.amount << std::endl;
    }
    
    double sumDebts(const Debt ar[], int n)
    {
        double total = 0;
        for (int i = 0; i < n; i++)
            total += ar[i].amount;
        return total;
    }
}

Deguchi

Legacy Member
Ik hoop dat ik hier de bal niet fout sla, maar een define kan ervoor zorgen dat je het probleem kan vermijden van dubbele includes(headers linken aan headers enz). Je header zal dus maar 1 keer geinclude worden en zal daarna genegeerd worden omdat de define reeds gedeclareerd is door een vorige include.

Hopelijk is het een beetje duidelijk :s

Tyfius

Legacy Member
Wat een #include statement eigenlijk doet is het kopiëren van de code uit het geincludeerde bestand in het bestand waar de #include gedaan wordt. Een voorbeeld:
foo.h
Code:
void bar();
foo.cpp
Code:
#include "foo.h"

void bar() {
    // Implementatie hier
}
Geeft eigenlijk:
Code:
void bar();

void bar() {
    // Implementatie hier
}
Wanneer je nu in een ander bron bestand ook "foo.h" gaan includeren dat ga je 2x een declaratie hebben van "void bar();" en gaat de compiler hier jou een waarschuwing op geven. Hij kent dit al, dus waarom zou je het opnieuw doen? De #ifndef, #define en #endif bij een header file gaan de compiler laten weten: "Indien nog niet gekend, definieer. Indien wel gekend (#ifndef is dus #if not defined), skip tot aan de #endif."

Xoliul

Legacy Member
Even een noob-vraag; doet #pragma once (VS specifiek commando?) hetzelfde als zo'n #ifndef dan ?

MacK

Legacy Member
VS 2005 geeft alleszins geen warnings als ik het compileer zonder die #ifndef.

Maar goed, bedankt voor de uitleg!

Tyfius

Legacy Member
Als je een header bestand maar 1x include ergens gaat dat geen warnings of errors geven (vrij logisch, je definieert niets 2x).

Een #pragma once doet in principe hetzelfde maar wordt niet door elke compiler ondersteund en bijgevolg wordt #ifndef aangeraden om te gebruiken.

Xoliul

Legacy Member
Aha, thx voor dat op te helderen, ik vermoede al dat het zoiets was. Ik zou wel denken dat het niet uitmaakt dat ik altijd met #pragma werk, aangezien ik toch alleen VS2005 beruik.

forloRn_

Legacy Member
Niet vergeten dat een compiler werkt op compilation units, en een compilation unit is een .cpp met alle .h geïncluded. Hier includen zowel usenmsp.cpp als namesp.cpp namesp.h, maar dit geeft voor de compiler geen problemen, omdat het hier om twee verschillende compilation units gaat die onafhankelijk van elkaar gecompileerd worden.

MacK

Legacy Member
Ha, ik versta het eindelijk. Ik had blijkbaar iets mislezen, en ik dacht dat een header file maar 1 maal mocht geïnclude zijn in uw project (wat helemaal niet logisch is). Maar nu dat ik het opnieuw lees in m'n boek: Een header mag maar 1 maal per bestand geïnclude zijn. Vandaar mijn verwarring.

Bedankt voor de vele antwoorden!

killgore

Legacy Member
forloRn_ zei:
Niet vergeten dat een compiler werkt op compilation units, en een compilation unit is een .cpp met alle .h geïncluded. Hier includen zowel usenmsp.cpp als namesp.cpp namesp.h, maar dit geeft voor de compiler geen problemen, omdat het hier om twee verschillende compilation units gaat die onafhankelijk van elkaar gecompileerd worden.

Maar verkeerd gebruik van includes kan zoals tyfius zegt wel tot "already defined" errors en dergelijke leiden.

En dit zijn fouten die je vindt bij het linken, niet bij het compilen.

(dit ter aanvulling, ik verbeter u niet of zo).
Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.
Terug
Bovenaan