Archief - Invullen waarde in klasse

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.

Curahee Q

Legacy Member
Beste 9livers

Op school zien wij C++ maar ben zelf al redelijk lang bezig met Java. Nu heb je wel eens in een klasse dat een membervariabele een standaardwaarde moet krijgen. In C++ kan dit enkel in de constructor geset worden maar in java is dit niet noodzakelijk. Setten jullie die value alsnog in de constructor bij java net zoals in C++?

Methode 1 (Java)
Code:
public class Car {

	private String color;
	private int speed;

	public Car(String color) {
		this.color = color;
		this.speed = 0;
	}
}

Methode 2 (Java)
Code:
public class Car {

	private String color;
	private int speed = 0;

	public Car(String color) {
		this.color = color;
	}
}

C++
Code:
class Car {
	public:
		Car(string color_p) {
			color = color_p;
			speed = 0;
		}

	private:
		string color;
		int speed;
}

Welke methode raden jullie mij aan in Java?

Tyfius

Legacy Member
Een andere mogelijkheid (althans in C++ en C#, ik ken te weinig van Java) is het volgende:
Code:
class Car
{
  public:
    Car(String color_p) : speed(2), color(color_p) {}
}
In theorie is dit iets sneller. Het object zal namelijk met die waarden worden geïnitialiseerd, in plaats van die eerst op hun default waarde te zetten en dan in je constructor die assignment te doen. (Eerst speed = 0, en dan in je constructor speed = 2 doen.) Hetzelfde geldt wanneer je ze bij de declaratie initialiseert.

Ik ben daar in principe een voorstander van. Ik vind dat overzichtelijker dan een hoop initialisaties in je constructor te gaan doen. Je kan er trouwens in de meeste talen van uitgaan dat default types op 0 of null worden geïnitialiseerd. Dat spaart ook al wat code uit.

Curahee Q

Legacy Member
die methode ken ik inderdaad ook al, maar ik wist niet dat ze sneller was. In C++ bestaat er toch geen default waarde, deze is in principe toch random aangezien je niet weet wat er op die geheugenplaats staat. In Java e.d. zijn er wel default waardes.

Gurdt

Legacy Member
@Tyfius: ik begrijp precies niet goed waarom dat sneller is? Wil je dat eens uitleggen? :)
Ik wist dat niet, ik dacht altijd dat dat gewoon voor de leesbaarheid was?
Ik neem trouwens aan dat je je membervariabelen vergeten bent? ;)

Edit: om even mijn vraag te verduidelijken, waarom is het eerste stukje code trager dan het tweede stukje code :)

Code:
class Aapke
{
    public:
        Aapke(int p) { m_p = p; }

        int m_p;
};
Code:
class Aapke
{
    public:
        Aapke(int p) : m_p(p) {}

        int m_p;
};

Curahee Q

Legacy Member
Is dat niet sneller omdat je dan niet eerst een default object(int, string) aanmaakt en dan pas daarna de verwijzing ofzo maakt naar je parameter? Echter bestaat er in C++ geen default waarde dacht ik.

Nu heb ik wel nog altijd geen antwoord op mijn vraag hoe het zit bij Java. Voorkeur of is er effectief 1 van de 2 beter?

Tyfius

Legacy Member
In C++ zijn alle POD types standaard op 0 geïnitialiseerd. [§8.5, ¶5]
To default-initialize an object of type T means:
  • if T is a non-POD class type (clause 9), the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);
  • if T is an array type, each element is default-initialized;
  • otherwise, the object is zero-initialized.

En het is inderdaad sneller omdat je een initialisatie over slaat. In dat eerste voorbeeld zal m_p eerst op 0 worden gezet, en dan zal de waarde van p daaraan worden toegekend in de constructor. In het 2de voorbeeld wordt m_p direct op de waarde van p gezet.

Nu hangen zo'n dingen ook veelal van de compiler af. Een goede compiler zal in veel gevallen waar mogelijk proberen zo'n dingen op te vangen en proberen op de snelste manier (indien mogelijk) te handelen.

En mijn persoonlijke voorkeur is methode 2, dat lijkt mij het meest logische en propere, behalve als de waarde dezelfde is als de default value.

Gurdt

Legacy Member
Ah ok, da geldt dus enkel voor primitieve types als ik het goed heb. Ja ik gebruik ook liever de 2e methode ;)

En over dat Java-ding, ik weet het eigenlijk niet, ik denk dat er geen enkele methode performanter is (in mijn ogen) maar methode 1 vind ikzelf leesbaarder.
Bij Java weet je natuurlijk nooit, wie weet wat die allemaal optimaliseert :) ik niet alleszins.

General Lee

Legacy Member
Initialiseren in de declaratie spaart een regel code uit :)

NeverwinterX

Legacy Member
Methode 2 is niet speciaal beter/slechter dan de 1, wel ietsje minder code. Als je methode 1 systematisch zou toepassen, heeft het wel als voordeel dat alle initialisatie stuff verzameld is op één plaats. Allebei de manieren zijn gangbaar.
Merk op dat de volgorde van initialisatie als volgt is:
- eerst de super klasse(n) constructors
- dan de initialisaties die bij de members staan
- dan de eigen constructor
Ik betwijfel ten zeerste of er een verschil is in performance tussen beide in Java.

Shaddix

Legacy Member
zoals Tyfius al vertelde zal het performanter zijn je attributen een waarde te geven met de constructor, ook in Java

veel verschil gaat de gebruiker wel niet ondervinden omdat de doorsnee klasse niet genoeg attributen heeft om bewust een vertraging te dedecteren bij het gebruik van de andere methode, maar het geeft sommige programmeurs gewoon voldoening ;)

er is natuurlijk ook nog een tweede voordeel aan het gebruiken van een constuctor: beveiliging

als je wil dat je attributen in het begin een waarde krijgen en daarna niet meer, dan kan je ze invullen via de constructor, en dan laat je de setters gewoon weg

forloRn_

Legacy Member
Java: inline, anders dupliceer je code als je meerdere constructors hebt. Als je initialisatie moeilijk is, gebruik je een initializer block.

C++: van die lelijke initializer lists. Je zal dat sowieso moeten doen als je members hebt die references zijn of als const gedeclareerd zijn.

En ik weet niet of C++ onlangs gewijzigd is, maar bij mijn weten hebben primitieve klassevariabelen geen default waarde. g++ geeft me hierin gelijk. Objecten worden wel geïnitialiseerd a.d.h.v. hun default constructor.

Tyfius

Legacy Member
forloRn_ zei:
Java: inline, anders dupliceer je code als je meerdere constructors hebt. Als je initialisatie moeilijk is, gebruik je een initializer block.

C++: van die lelijke initializer lists. Je zal dat sowieso moeten doen als je members hebt die references zijn of als const gedeclareerd zijn.

En ik weet niet of C++ onlangs gewijzigd is, maar bij mijn weten hebben primitieve klassevariabelen geen default waarde. g++ geeft me hierin gelijk. Objecten worden wel geïnitialiseerd a.d.h.v. hun default constructor.
Er is wel een verschil.
Code:
#include <iostream>
using namespace std;

class Car {
	public:
		Car() {}
		void Print() { cout << "Color: " << m_color << endl; }

	private:
		int m_color;
};
Color = 0
Code:
int main(void) {
	Car *car_1 = new Car();
	car_1->Print();
	delete car_1;

	return 0;
}
Color = uninitialized
Code:
int main(void) {
	Car car_2;
	car_2.Print();

	return 0;
}
Color in beide gevallen 0. (for some strange reason)
Code:
int main(void) {
	Car *car_1 = new Car();
	car_1->Print();
	delete car_1;

	Car car_2;
	car_2.Print();

	return 0;
}

General Lee

Legacy Member
forloRn_ zei:
Java: inline, anders dupliceer je code als je meerdere constructors hebt.
Ge kunt toch de ene constructor de andere laten aanroepen?

Gurdt

Legacy Member
Zeg Tyfius, in alle 3 de gevallen is het niet geïnstantieerd hoor ;)
In C++ toch niet.

Edit: uw eerste 2 en uw 3e spreken elkaar trouwens compleet tegen ;) ene keer is het 0 en andere keer niet ofwa? :')
Neje, tis altijd garbage :)

MAXXUR

Legacy Member
Code:
Car() {}

nét hierom overschrijft ge de default constructor die zaken op 0 initialiseert :)

Gurdt

Legacy Member
MAXXUR zei:
Code:
Car() {}

nét hierom overschrijft ge de default constructor die zaken op 0 initialiseert :)

Juist, en moest ge die weglaten dan gaat die klasse waarop ge geen new doet ook nog altijd niet geïnitialiseerd worden

Tyfius

Legacy Member
Gurdt zei:
Zeg Tyfius, in alle 3 de gevallen is het niet geïnstantieerd hoor ;)
In C++ toch niet.

Edit: uw eerste 2 en uw 3e spreken elkaar trouwens compleet tegen ;) ene keer is het 0 en andere keer niet ofwa? :')
Neje, tis altijd garbage :)
Example 1:
Code:
root@mini-cooper:~/test# ./a.out
Color: 0
Example 2:
Code:
root@mini-cooper:~/test# ./a.out
Color: -1208459792
Example 3:
Code:
root@mini-cooper:~/test# ./a.out
Color: 0
Color: -1082085912
Example 3 zal puur toeval geweest zijn, bij mij thuis vanmorgen (andere GCC wel dan hier op kantoor) gaf die in beide gevallen 0 terug. Maarja, GCC is ook maar een implementatie en interpretatie van de standaard he (die trouwens wel zegt dat het 0 moet zijn, zoals ik eerder al gequote heb). Dat is in de laatste versie wel te zien aan hun strict alias interpretatie. Het verbaasde mij ook, vandaar dat ik het erbij gezet had.

Shaddix

Legacy Member
Gurdt zei:
Juist, en moest ge die weglaten dan gaat die klasse waarop ge geen new doet ook nog altijd niet geïnitialiseerd worden

een klasse waarge geen nul op doet gaat dat zowiezo niet worden volgens mij

Gurdt

Legacy Member
Ja de uitkomst die ge nu geeft bekom ik alleen als k de standaard constructor niet overschrijf :)
Ma het hangt dus af van de compiler maw...
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