C++-ohjelmoinnin aloittaminen

Syntaksi ja kääntäminen


Huomautus

Tässä kohdassa (ja muuallakin materiaalin alkupäässä) Python- ja C++-ohjelmia vertaillaan toisiinsa. Python on valittu vertailukieleksi, koska useimmat opiskelijat osaavat Pythonia Ohjelmointi 1:n pohjalta. Jos et kuitenkaan osaa Pythonia, vertailukohdissa riittää kiinnittää huomiota C++-osuuksiin.

Tässä osiossa katsotaan ensin, miltä pieni C++-ohjelma näyttää ja minkälaisia yksityiskohtia siihen liittyy. Vertaillaan seuraavia Python- ja C++-ohjelmia, jotka ovat toiminnaltaan täysin identtisiä:

Versio 1: Pythonilla

def main():
    print("Hello world!")
    print("Mitä kuuluu?")

main()

Versio 2: C++:lla

#include <iostream>

using namespace std;

int main() {
    cout << "Hello world!" << endl;
    cout << "Mita kuuluu?"
         << endl;
}

Tutkitaan eroja ja yhtäläisyyksiä ohjelmien välillä.

  • C++-ohjelma käynnistyy aina automaattisesti main-funktiosta.
  • Pythonissa pääohjelmafunktio nimettiin main:ksi vain käytännön syistä, koska monissa muissakin ohjelmointikielissä käytetään samaa nimeä. Python ei vaadi tällaista nimeämiskäytäntöä, mutta C++ vaatii.
  • Suurin osa C++-käskyistä päättyy puolipisteeseen. Sääntö ei kuitenkaan koske kaikkia tilanteita, joten puolipistettä ei voi lisätä kaikkialle. Aloittelijalle voi olla vaikeaa hahmottaa, mihin puolipiste kuuluu.
  • Koska käskyt päättyvät useimmiten puolipisteeseen, C++ sallii käskyjen jakamisen usealle riville ilman erityismerkintää. Pythonissa katkaistun rivin loppuun tarvitaan yleensä \-merkki osoittamaan, että käsky jatkuu seuraavalla rivillä.
  • C++-ohjelman lohkot merkitään aaltosulkeilla { }. Pythonissa lohkot ilmaistaan sisennyksillä. Sisennyksiä kannattaa käyttää myös C++:ssa, koska ne helpottavat ohjelman rakenteen hahmottamista.
  • C++-ohjelman kommenttimerkki on //. Pythonissa kommentit aloitetaan #-merkillä.
  • C++-kieli ei sisällä tulostuskäskyä, vaan tulostaminen on toteutettu kirjastossa. Näytölle tulostaminen ja näppäimistöltä lukeminen edellyttävät iostream-kirjaston käyttöönottoa:
    #include <iostream>

    #include <...> vastaa C++:ssa Pythonin import-käskyä. Sillä otetaan käyttöön toisessa tiedostossa olevaa ohjelmakoodia. Kulmasulkeisiin kirjoitetaan kirjaston nimi, kun kääntäjän halutaan etsivän tiedosto C++:n kirjastohakemistoista. Itse toteutetun tiedoston nimi kirjoitetaan lainausmerkkien sisään.

    #-merkillä alkavat rivit ovat esiprosessorin direktiivejä. Esiprosessori valmistelee ohjelmakooditiedostot ennen varsinaista käännöstä. Se tekee tekstikorvauksia: esimerkiksi #include <iostream> korvaa direktiivin nimetyn tiedoston sisällöllä.

  • cout ja tulostusoperaattori << tulostavat tietoa näytölle. Voit tulostaa samalla cout-käskyllä useita arvoja lisäämällä kunkin eteen <<-operaattorin. endl siirtää kursorin seuraavan rivin alkuun.
  • C++-koodissa on lisäksi rivi using namespace std;. Sen ansiosta iostream-kirjaston nimiä, kuten cout ja endl, voidaan käyttää sellaisenaan ilman etuliitettä std::.

    Pythonissa on vastaava mekanismi, jota ei edellisessä esimerkissä käytetty. Kirjastoa voi käyttää etuliitteen kanssa:

    import math
    ...
    math.sqrt(2.0)

    Kirjaston nimen voi jättää pois kirjoittamalla:

    from math import *
    ...
    sqrt(2.0)

    using namespace mahdollistaa nimiavaruudessa määriteltyjen tunnisteiden käyttämisen ilman nimiavaruuden nimeä etuliitteenä. Etuliitteistä voi kuitenkin olla hyötyä. Nimiavaruus kokoaa tunnisteita yhteen ja auttaa välttämään samannimisten tunnisteiden sekoittumisen. Esimerkiksi opintorekisteriohjelmassa voidaan viitata opiskelijan nimeen muodossa Opiskelija::nimi ja opintojakson nimeen muodossa Opintojakso::nimi. Tämä on tärkeää erityisesti suurissa ohjelmissa, joissa tunnisteita on paljon.

    Ilman using namespace -käskyä ohjelma näyttää tältä:

    // Versio 3: tyylillisesti parempi C++-ohjelma
    #include <iostream>
    
    int main() {
        std::cout << "Hello world!" << std::endl;
        std::cout << "Mita kuuluu?"
                  << std::endl;
    }

    Vaikka yllä oleva koodi on tyylillisesti parempi, tällä kurssilla käytetään pääsääntöisesti yksinkertaisempaa tapaa, koska Qt generoi edellä mainitun using-komennon automaattisesti.

Tämän kierroksen materiaaleista löytyy kolme esimerkkiä, joiden tarkoituksena on auttaa tutustumaan C++:n syntaksiin.

  • arithmetic_series liittyy kontrollirakenteisiin, erityisesti for-lauseeseen.
  • rock_paper_scissors liittyy kontrollirakenteisiin, erityisesti if- ja while-lauseisiin. Lisäksi siinä näkyy merkkijonojen ja merkkien käyttö.
  • triangle liittyy funktioihin.

Ei haittaa, vaikka et ymmärtäisi esimerkkiohjelmien logiikkaa. Tässä vaiheessa on tärkeämpää oppia lukemaan C++-koodia.

Tulkattavat ja käännettävät ohjelmointikielet

Python on tulkattava ohjelmointikieli ja C++ käännettävä ohjelmointikieli.

Tulkattavan ohjelmointikielen suorittamiseen tarvitaan erillinen apuohjelma eli tulkki jokaisella suorituskerralla. Esimerkiksi Python-ohjelmien suorittamiseen tarvitaan Python-tulkki. Jos tulkki poistetaan tai se tuhoutuu, ohjelmia ei voi suorittaa ennen tulkin asentamista uudelleen. Tulkki muuttaa lähdekoodin käskyjä konekielelle ohjelman suorituksen edetessä, jotta tietokoneen prosessori pystyy suorittamaan ne.

Käännettävän ohjelmointikielen ohjelma käännetään ennen suorittamista kokonaisuudessaan konekieliseksi. Kääntämiseen käytetään ohjelmointikielen kääntäjää, kuten C++-kääntäjää.

Käännöksen aikana kääntäjä tarkistaa lähdekoodin virheitä ja tuottaa konekielisen ohjelman, joka tallennetaan yleensä erilliseen tiedostoon (Windowsissa esimerkiksi .exe-päätteiseen tiedostoon). Kun ohjelma on käännetty, kääntäjää ei enää tarvita sen suorittamiseen. Jos lähdekoodia muutetaan, se täytyy kääntää uudelleen, jotta muutokset tulevat mukaan ohjelmaan.

Monet ohjelmointikielet sijoittuvat tulkattavien ja käännettävien kielten välimaastoon. Niillä kirjoitetut ohjelmat voidaan kääntää välikoodiksi, jota sitten tulkataan. Tämä on tulkkauksen ja kääntämisen välimuoto.

Linkitys

Tarkasti ottaen kääntäminen sisältää vähintään kaksi vaihetta. Ensin ohjelma käännetään objektitiedostoksi. Se sisältää konekoodia, mutta sitä ei voi vielä suorittaa, koska lopullinen ohjelma tarvitsee osia kirjastoista. Siksi ohjelma täytyy vielä linkittää.

Linkityksessä erikseen käännetyt osat liitetään yhteen ajettavaksi ohjelmaksi. Kääntäjät yleensä piilottavat linkitysvaiheen, mutta suurissa ohjelmistoissa ohjelmaa kannattaa kääntää osissa, jotta jokaista pientä muutosta varten ei tarvitse kääntää kaikkea uudelleen. Hyöty korostuu suurissa ohjelmissa, mutta siitä voi olla apua pienemmissäkin ohjelmissa.