|
You last visited: Today at 16:29
Advertisement
Wozu Destruktor
Discussion on Wozu Destruktor within the C/C++ forum part of the Coders Den category.
06/29/2016, 14:23
|
#1
|
elite*gold: 309
Join Date: Jul 2011
Posts: 4,311
Received Thanks: 886
|
Wozu Destruktor
Hallo,
ist es sinnvoll in C++ nach einem Konstruktor auch den Destruktor zu programmieren und aufzurufen? Ist dachte der würde automatisch aufgerufen werden?
|
|
|
06/29/2016, 14:39
|
#2
|
elite*gold: 0
Join Date: Feb 2011
Posts: 1,206
Received Thanks: 736
|
die explizite implementation eines dekonstruktors kann in vielen fällen nötig sein, halt um dinge aufzuräumen die im verlauf des objekts oder im konstruktor erstellt wurden.
der destruktor wird genauso "automatisch" aufgerufen wie der konstruktor.
konstruktor beim new oder explizit, dekonstruktor beim delete oder explizit - wobei die jeweiligen expliziten aufrufe meist zeichen für fehlerhaftes design sind.
|
|
|
06/29/2016, 16:08
|
#3
|
elite*gold: 309
Join Date: Jul 2011
Posts: 4,311
Received Thanks: 886
|
Okay verstehe...
Ich habe bei meinem Projekt gerade ein ganz anderes Problem:
Bekomme den Fehler: ' ... ' was not declared in this scope (also meine Funktionen)
Woran kann das liegen?
main:
Code:
#include <iostream>
#include "Bruch.h"
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
using namespace std;
int main(int argc, char** argv) {
Bruch *b1, *b2;
b1 = new Bruch(2,1);
b2 = new Bruch(2,1);
print(b1);
return 0;
}
Bruch.cpp
Code:
#include "Bruch.h"
#include <iostream>
//Konstruktor
Bruch::Bruch(int z, int n)
{
zaehler = z;
nenner = n;
}
//setter
void Bruch::setBruch(int z, int n)
{
if(n != 0)
{
zaehler = z;
nenner = n;
}
else
{
std::cout << "Fehler: Nenner darf nicht 0 betragen!" << std::endl;
}
}
//getter
float Bruch::getBruch()
{
return (float)zaehler/(float)nenner;
}
//print
void Bruch::print(Bruch b1)
{
std::cout << b1.zaehler << "/" << b1.nenner << std::endl;
}
//mult
float Bruch::mult(Bruch b1, Bruch b2)
{
return (b1.zaehler * b2.zaehler) / (b1.nenner * b2.nenner);
}
Bruch.h
Code:
class Bruch{
private:
int zaehler;
int nenner;
public:
Bruch(); //Standartkonstruktor
Bruch(int,int); //Costum-Konstruktor
void setBruch(int,int);
float getBruch();
void print(Bruch);
float mult(Bruch, Bruch);
};
|
|
|
06/29/2016, 17:16
|
#4
|
elite*gold: 46
Join Date: Oct 2010
Posts: 782
Received Thanks: 525
|
Die print Funktion die du in Bruch.cpp definiert hast ist nicht Teil der Klasse, deswegen können auch die Variablen nicht gefunden werden.
|
|
|
06/29/2016, 17:32
|
#5
|
elite*gold: 309
Join Date: Jul 2011
Posts: 4,311
Received Thanks: 886
|
Quote:
Originally Posted by C0untLizzi
Die print Funktion die du in Bruch.cpp definiert hast ist nicht Teil der Klasse, deswegen können auch die Variablen nicht gefunden werden.
|
Ups. Da ist etwas beim Kopieren verloren gegangen. Ich habe jetzt in der Bruch.cpp wieder das Bruch:: vor die Funktion angefügt. An der Fehlermeldung ändert das nichts. Das Problem hab ich bei allen definierten Funktionen.
|
|
|
06/29/2016, 18:07
|
#6
|
elite*gold: 46
Join Date: Oct 2010
Posts: 782
Received Thanks: 525
|
In main müsstest du b1->print() aufrufen wenn du print als Funktion der Klasse definiert hast. Btw würde die genaue Fehlermeldung schon helfen.
|
|
|
06/29/2016, 18:51
|
#7
|
elite*gold: 309
Join Date: Jul 2011
Posts: 4,311
Received Thanks: 886
|
Quote:
Originally Posted by C0untLizzi
In main müsstest du b1->print() aufrufen wenn du print als Funktion der Klasse definiert hast. Btw würde die genaue Fehlermeldung schon helfen.
|
Danke. Das wars!
|
|
|
07/07/2016, 15:22
|
#8
|
elite*gold: 420
Join Date: Jan 2012
Posts: 1,082
Received Thanks: 1,000
|
Heir bietet es sich an semantisch sinnvoll die Operatoren zu überladen. Das ganze würde dann in etwa so aussehen.
Code:
// https://github.com/gcc-mirror/gcc/blob/edd716b6b1caa1a5cb320a8cd7f626f30198e098/libstdc%2B%2B-v3/include/experimental/numeric#L55
template<typename _Mn, typename _Nn>
constexpr std::common_type_t<_Mn, _Nn>
gcd(_Mn __m, _Nn __n) {
static_assert(std::is_integral<_Mn>::value, "arguments to gcd are integers");
static_assert(std::is_integral<_Nn>::value, "arguments to gcd are integers");
return __m == 0 ? std::abs(__n)
: __n == 0 ? std::abs(__m)
: /*fundamentals_v2::*/gcd(__n, __m % __n);
}
class fraction
{
public:
fraction(int numerator, int denominator)
: numerator(numerator), denominator(denominator)
{}
friend std::ostream& operator<<(std::ostream& os, const fraction& f);
fraction &reduce() {
fraction tmp(*this);
tmp /= gcd(numerator, denominator);
return tmp;
}
fraction &reciprocal() {
fraction r(denominator, numerator);
return r;
}
fraction &operator*=(const fraction &rhs) {
numerator *= rhs.numerator;
denominator *= rhs.denominator;
return *this;
}
fraction &operator*=(int factor) {
numerator *= factor;
// denominator *= 1
return *this;
}
fraction &operator/=(const fraction &rhs) {
*this *= rhs.reciprocal()
return *this;
}
fraction &operator/=(const int factor) {
denominator *= factor;
return *this;
}
fraction &operator+=(const fraction &rhs) {
numerator = (numerator * rhs.denominator) + (rhs.numerator * denominator);
denominator = denominator * rhs.denominator;
}
fraction &operator+=(int factor) {
numerator += denominator;
return *this;
}
operator int() const
{ return static_cast<int>(static_cast<float>(*this)); }
operator float() const
{ return static_cast<float>(numerator) / static_fast<float>(denominator); }
private:
int numerator;
int denominator;
}
std::ostream& operator<<(std::ostream& os, const fraction& f) {
os << f.numerator << '/' << f.denominator;
return os;
}
|
|
|
07/07/2016, 20:37
|
#9
|
elite*gold: 0
Join Date: Jul 2016
Posts: 2
Received Thanks: 0
|
sehr gut ausgeführt von Dr. Coxxy, wenn du viel mit dem heap also pointer und neu erzeugten feldern arbeitest bietet es sich zb sehr gut dort an diesen wieder sauber zu entladen und diese felder wieder frei zugeben, bei bearbeiten von großen datenmengen ist eine saubere verwaltung des speichers mit das wichtigste sonst sprengt dir die anwendung den rahmen deines speichers
|
|
|
07/11/2016, 15:43
|
#10
|
elite*gold: 7110
Join Date: Jun 2009
Posts: 28,905
Received Thanks: 25,407
|
Quote:
Originally Posted by Dr. Coxxy
die explizite implementation eines dekonstruktors kann in vielen fällen nötig sein, halt um dinge aufzuräumen die im verlauf des objekts oder im konstruktor erstellt wurden.
der destruktor wird genauso "automatisch" aufgerufen wie der konstruktor.
konstruktor beim new oder explizit, dekonstruktor beim delete oder explizit - wobei die jeweiligen expliziten aufrufe meist zeichen für fehlerhaftes design sind.
|
Quote:
Originally Posted by NRj™
Okay verstehe...
Ich habe bei meinem Projekt gerade ein ganz anderes Problem:
Bekomme den Fehler: ' ... ' was not declared in this scope (also meine Funktionen)
Woran kann das liegen?
main:
Code:
#include <iostream>
#include "Bruch.h"
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
using namespace std;
int main(int argc, char** argv) {
Bruch *b1, *b2;
b1 = new Bruch(2,1);
b2 = new Bruch(2,1);
print(b1);
return 0;
}
Bruch.cpp
Code:
#include "Bruch.h"
#include <iostream>
//Konstruktor
Bruch::Bruch(int z, int n)
{
zaehler = z;
nenner = n;
}
//setter
void Bruch::setBruch(int z, int n)
{
if(n != 0)
{
zaehler = z;
nenner = n;
}
else
{
std::cout << "Fehler: Nenner darf nicht 0 betragen!" << std::endl;
}
}
//getter
float Bruch::getBruch()
{
return (float)zaehler/(float)nenner;
}
//print
void Bruch::print(Bruch b1)
{
std::cout << b1.zaehler << "/" << b1.nenner << std::endl;
}
//mult
float Bruch::mult(Bruch b1, Bruch b2)
{
return (b1.zaehler * b2.zaehler) / (b1.nenner * b2.nenner);
}
Bruch.h
Code:
class Bruch{
private:
int zaehler;
int nenner;
public:
Bruch(); //Standartkonstruktor
Bruch(int,int); //Costum-Konstruktor
void setBruch(int,int);
float getBruch();
void print(Bruch);
float mult(Bruch, Bruch);
};
|
Wichtig ist aber auch, dass C++ eben nicht gleich Java ist. In C++ verwendest du das new-Schlüsselwort wesentlich seltener (bis hin zu gar nicht, seit C++11/14) als in Java, wo damit jedes Objekt erzeugt wird. new/delete wird nur für Objekte auf dem Heap verwendet (und auch da solltest du lieber zu Smartpointern und den entsprechenden Hilfsfunktionen greifen, um new/delete zu umgehen), für Objekte auf dem Stack ist das nicht notwendig. Letztere sind wenn möglich zu bevorzugen, weil du dich dann nicht darum kümmern musst, den Speicher wieder freizugeben - das passiert bei Objekten auf dem Stack automatisch. Der Konstruktor wird auch nicht nur bei new aufgerufen und der Destruktor nicht nur bei delete, sondern eben auch beim Auf- und Abbau des Stackframes.
Dein Code enthält (aufgrund o.g. Thematik) ein Memory Leak (auch wenn es in deinem Programm keine Auswirkung hat, weil das System beim Beenden des Programms den Speicher wieder freigibt). Du reservierst Speicher mit new, aber gibst ihn mit delete nicht mehr frei. Das solltest du auf jeden Fall vermeiden.
Zwar könntest du das beheben, indem du ans Ende der main die Objekte per delete wieder zerstörst, aber folgender Code wäre ebenfalls möglich (und besser):
Code:
#include <iostream>
#include "Bruch.h"
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
using namespace std;
int main(int argc, char** argv) {
Bruch b1(2, 1), b2(2, 1); //alternativ: b1{2, 1} und b2{2, 1}
b1.print();
return 0;
}
|
|
|
07/18/2016, 18:04
|
#11
|
elite*gold: 420
Join Date: Jan 2012
Posts: 1,082
Received Thanks: 1,000
|
Quote:
|
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
|
wat?
> int main(int argc, char** argv)
Quote:
|
Originally Posted by n4594 -- 3.6.1 Main Function -- basic.start.main
An implementation shall allow both
(2.1) — a function of () returning int and
(2.2) — a function of (int, pointer to pointer to char) returning int
|
> return 0;
Quote:
|
Originally Posted by n4594 -- 3.6.1 Main Function -- basic.start.main
A return statement in main has the effect of leaving the main function (destroying any objects with automatic
storage duration) and calling std::exit with the return value as the argument. If control flows off the end
of the compound-statement of main, the effect is equivalent to a return with operand 0 (see also 15.3).
|
pls
|
|
|
07/19/2016, 22:37
|
#12
|
elite*gold: 7110
Join Date: Jun 2009
Posts: 28,905
Received Thanks: 25,407
|
Was willst du uns mitteilen?
|
|
|
07/21/2016, 18:09
|
#13
|
elite*gold: 420
Join Date: Jan 2012
Posts: 1,082
Received Thanks: 1,000
|
Dazu bedarf es keines weiteren Kommentars, es sollte hinlänglich ersichtlich sein.
|
|
|
07/21/2016, 19:25
|
#14
|
elite*gold: 0
Join Date: Feb 2011
Posts: 1,206
Received Thanks: 736
|
um ehrlich zu sein ich check auch nicht was du uns sagen willst - die offensichtliche antwort wäre, dass du entweder ziemlich dämlich bist, oder ich dich missverstanden habe - Mr. Smiths freundliche auslegung war halt letztere
|
|
|
07/21/2016, 19:55
|
#15
|
elite*gold: 966
Join Date: Apr 2010
Posts: 1,105
Received Thanks: 681
|
Ich vermute, dass P.File auf Folgendes hinaus wollte:
a) es wurde im Beispielcode explizit system("pause") empfohlen (hier bin ich mir nicht sicher, ob dass wirklich Ziel der Nachricht / Kritik war),
b) "int main()" als Signatur des Einstiegspunktes reicht völlig aus, weil es standardkonform ist und auf argc und argv nicht zugegriffen wird und
c) "return 0" am Ende von main ist unnötig, weil das durch den Standard schon implizit gegeben ist.
Generell ist das sicher alles korrekt, wobei ich den Vorteil von b und c nicht erkennen kann, außer, dass die Source-Datei etwas weniger Bytes hat. Gut, bei b kann der Compiler noch Optimierungen machen, so dass argc / argv gar nicht vom Betriebssystem geholt werden muss, aber das halte ich eher für eine kleinere Optimierung und könnte sogar in der aktuellen Form geschehen, weil der Compiler "merkt", dass argc / argv nie benutzt werden.
Mit freundlichen Grüßen
Jeoni
|
|
|
 |
|
Similar Threads
|
Wozu Surakopf?
08/19/2012 - Metin2 Private Server - 4 Replies
Hallo liebe Com. :)
Ich habe da mal ne Frage:
Wozu deint eigentlich die Surakopf.exe? (Das man sie braucht um den CLient als USER zu Starten weiß ich) Aber warum können normale User eines Hamachi Servers nicht auch mit der Metin2Client.exe rein? Denn meine Surakopf Scheißt immer ab nach dem Patchen deshalb kann man das irgendwie so einstellen das auch Hamachi User mit der Metin2Client.exe auf den Server können?
MfG XxKeynanxX
|
Wozu ist der Bypass?
09/25/2011 - S4 League - 12 Replies
ja, ich wollte fragen was der Bypass nützt, und was er kann.
MfG
|
Wozu eg?
01/25/2011 - Main - 1 Replies
Weiß einer wozu eg ist wen ja in den topic schreiben >:P
|
Wozu?
11/26/2010 - S4 League - 3 Replies
Habe mal ne dumme Frage...wozu sind Suspender gut für S4 ich spiele das slebst nicht lange...Deswegen halt meine Frage!
|
/ski - wozu ?
05/15/2009 - Metin2 Private Server - 4 Replies
Ich lese in letzer zeit immer was von "/ski cheats" auf pservern -.-
1)Was ist das ?oO
2Was bewirkt das ?
3)Welche /ski cheats gibts ?^^
Wäre nett wenn ihr antwortet =)
|
All times are GMT +1. The time now is 16:30.
|
|