Yksi määritelmäsääntö

Kokeneet kirjoittajat eivät ole vielä tarkistaneet sivun nykyistä versiota, ja se voi poiketa merkittävästi 16. maaliskuuta 2021 tarkistetusta versiosta . vahvistus vaatii 1 muokkauksen .

One Definition Rule (ODR) on yksi C++-ohjelmointikielen  perusperiaatteista . ODR:n tarkoituksena on estää kahden tai useamman ristiriitaisen määritelmän esiintyminen samasta entiteetistä ( tietotyyppi , muuttuja , funktio , objekti , malli ) ilmestymästä ohjelmaan. Jos tätä sääntöä noudatetaan, ohjelma käyttäytyy ikään kuin siinä olisi vain yksi yleinen määritelmä mille tahansa kokonaisuudelle. ODR-rikkomus, jos sitä ei havaita projektin kääntämisen ja kokoonpanon aikana, johtaa ohjelman ennakoimattomaan toimintaan .

Syitä

C++-kielen syntaksi määrää useille entiteeteille tarpeen yhdistää kuvaus ilmoitukseen tai selityksen päällekkäisyys. Tämä johtuu siitä, että kielessä ei ole täysimittaista modulaarisuuden tukea, minkä vuoksi tiedoston käännösvaiheessa sen tekstissä (eli itse käännetyn moduulin tekstissä ja kaikkien kielen otsikkotiedostojen tekstissä se ) sisältää kääntäjälle riittävät tiedot kaikista käytetyistä muissa käännösyksiköissä määritellyistä ohjelmakokonaisuuksista . Joten esimerkiksi kääntääksesi tiedoston, joka käyttää tiettyä luokkaa, sinun on määritettävä ainakin itse luokka ja sen julkiset ominaisuudet ja menetelmät , ja jos haluat käyttää tiedostossa rivin sisäistä ( inline ) -funktiota, jokaisen käyttävän tiedoston tulee sisältää sen koko teksti. On selvää, että kaikkien tällaisten määritelmien on oltava identtisiä ohjelman johdonmukaisuuden varmistamiseksi. Tämä varmistetaan yleensä sillä, että käännösyksikön rajapinta- osa on kuvattu sopivassa otsikkotiedostossa, joka sitten sisällytetään sinne missä on tarpeen käyttää siinä määriteltyjä entiteettejä. Mutta todellisuudessa mikään ei estä sinua sisällyttämästä erilaisia ​​kuvauksia samoista ohjelmaelementeistä eri käännetyissä tiedostoissa. Kääntäjä ei pysty havaitsemaan tällaista virhettä, koska se käsittelee käännöshetkellä vain yhden moduulin koodin.

Toinen törmäys on mahdollinen, kun ohjelmassa on kaksi eri määritelmää samalle elementille tai ulkoisen ilmoituksen (ulkoisen määritteen kanssa) ja saman elementin todellisen määritelmän välillä on ristiriita. Esimerkiksi jos funktion ulkoisessa määrittelyssä ja sen määrittelyssä on eri määrä parametreja , funktiokutsu on virheellinen, mutta kääntäjä ei pysty havaitsemaan tätä, koska työskentelyhetkellä se näkee vain yhden käännöksen yksikkö.

Kuuluisassa kirjassaan Introduction to the C++ Language Bjorn Stroustrup antaa seuraavan esimerkin:

// tiedosto1.c: int a = 1; int b = 1; extern int c; // file2.c: int a; ulkoinen kaksinkertainen b; extern int c;

Tässä esimerkissä on 3 virhettä: a on määritelty kahdesti ("int a;" on määritelmä, jossa a:n alkuarvoa ei ole asetettu), b :llä on eri tyypit ilmoituksessa ja määritelmässä ja c ilmoitetaan kahdesti, mutta ei määritelty. Kääntäjä ei pysty havaitsemaan tällaisia ​​C++:n virheitä . Useimmissa tapauksissa linkkeri havaitsee ne .

C++:n toistuville määrityksille ja ohjelmakokonaisuuksille asetetut rajoitukset, joiden noudattaminen takaa tällaisten ilmoitusten ja määritelmien asianmukaisen käsittelyn, on tiivistetty kielikuvauksessa ns. "Yhden määritelmän sääntöön".

Sääntömääräykset

  1. Missä tahansa käännösyksikössä mallilla , tietotyypillä , funktiolla tai objektilla voi olla vain yksi määritelmä, vaikka niillä voi olla rajoittamaton määrä ilmoituksia. Määritelmä tuottaa kokonaisuuden.
  2. Ohjelman sisällä ( kaikkien käännösyksiköiden joukko) ulkoisella objektilla tai ulkoisella ei-inline- funktiolla voi olla vain yksi määritelmä; jos käytetään objektia tai funktiota, jokaisella niistä on oltava täsmälleen yksi määritelmä. Voit ilmoittaa objektin tai funktion, jota ei käytetä ohjelmassa, jolloin niitä ei myöskään tarvitse määritellä. Määritelmiä ei saa missään tapauksessa olla useampia.
  3. Tyypit, mallit ja rivifunktiot (eli ne entiteetit, joiden määritelmä on yhdistetty kokonaan tai osittain ilmoitukseen) voidaan määrittää useampaan kuin yhteen käännösyksikköön, mutta jokaisen sellaisen entiteetin kaikkien määritelmien on oltava identtisiä.
  4. Ei-ulkoiset objekti- ja funktiomääritykset eri käännösyksiköissä määrittelevät eri entiteetit, vaikka niiden nimet ja tyypit olisivat samat. Nämä määritelmät voivat vaihdella vapaasti.

Kääntäjä voi löytää joitakin ODR-rikkomuksia , mutta useimmat havaitaan vain linkin aikana.

Lisätietoja