Benutzer mit den meisten Antworten
CTime akzeptiert keine Sekunden über 59

Frage
-
Hallo Forum
Ich arbeite mit einem Diagrammobjekt, das auf der X-Achse mit Uhrzeiten arbeiten muss. Eigentlich nichts schlimmer als das, weil eine Skala vernünftig mit Uhrzeiten zu versehen ist eine eigene Wissenschaft und verlangt mir jede Menge "cases" ab, da die Darstellung im Bereich von Sekunden stark von der im Bereich von Tagen oder Monaten varriert.
Lange Rede kurzer Sinn, ich habe für die Achsenraster Schleifen, die Sekunden oder Minuten oder auch Tage weiterzählen und wollte das mit einem CTime-Objekt erledigen, das ich einfach folgendermaßen initialisiert habe:
CTime CT; ... // aktuelle Zeit CT CTime NewTime(CT.GetYear(),CT.GetMonth()+1,1,0,0,0);
Im Beispiel zähle ich das Monat weiter und hole mir dann mit
CTime.GetTime()
wieder einen Sekundenwert, damit ich alles auf der Skala richtig eintragen kann.
Das Problem ist aber, dass ich auf diese Weise natürlich über eine Begrenzung springe (z.B. wenn vorher schon Dezember war) und CTime ist offenbar unflexibel genug, mir dann eine ASSERTION zu schmeißen, anstelle das Jahr hochzuzählen.
Also hätte ich geglaubt, einfach eine CTimeEx Klasse von CTime abzuleiten, alle Funktionen zu erben und einfach den Konstruktor umzuschreiben:
class CTimeEx:public CTime { public: CTimeEx(int nYear,int nMonth,int nDay,int nHour,int nMinute,int nSecond); }; CTimeEx::CTimeEx(int nYear,int nMonth,int nDay,int nHour,int nMinute,int nSecond) { int mon_tab[]={31,28,31,30,31,30,31,31,30,31,30,31}; nDay--; nMonth--; nMinute += nSecond/60; nSecond = nSecond % 60; nHour += nMinute/60; nMinute = nMinute % 60; nDay += nHour/24; nHour = nHour % 24; while (nDay >= mon_tab[nMonth%12]) { nDay -= mon_tab[nMonth%12]; nMonth++; } nYear += nMonth/12; nMonth = nMonth % 12; CTime(nYear,nMonth+1,nDay+1,nHour,nMinute,nSecond); }
Abgesehen davon, dass in dem Beispielcode die Schaltjahre noch nicht berücksichtigt werden, ist mir die Syntax jetzt nicht ganz klar, mit der ich der Basisklasse die Werte übergebe. So wie im Beispiel funktioniert's offenbar nicht. Die Syntax mit dem Doppelpunkt gleich nach dem Funktionsnamen kenne ich, da werden die Parameter aber übergeben, bevor ich sie ändern konnte, oder?
Wie sieht die korrekte Syntax aus?
Grüße
FireHeart
Antworten
-
Direkt geht das nicht, sehe ich auch nicht denn Sinn über die gleichen Parameter was anderes zu machen.
In der abgeleiteten Klasse die Parameter für die Basce Klasse zu ändern könntem an sich hintricksen. Du benötigst halt einen Default Constuctor in der BaseClass, auch wenn Du den nicht explizit aufrufst. Zur not könntest Du den leer lassen.
In Deinem Fall wären virtuelle Konstruktoren das Mittel, die gibt es abern icht in C++...
Zu Deinem Problem wäre der Codeschnipsel vielleicht ein Umweg. Der Default Konstructor würde nur existieren ohne Funktionalität. Je nachdem könnte vielleicht dieser Ansatz Dein Problem lösen, nicht schön, und auch sicher nicht so gedacht, aber wäre ein Ansatz...
------ Base Header ------ class BaseClass { public: BaseClass(); BaseClass(int a, int b); ~BaseClass(void); }; ------ Base Class ------ #include "BaseClass.h" BaseClass::BaseClass() { } BaseClass::BaseClass(int a, int b) { } BaseClass::~BaseClass(void) { } ------ Derived Header ------ #include "baseclass.h" class NewClass : public BaseClass { public: NewClass(int a, int b); ~NewClass(void); }; ------ Derived Class ------ #include "newclass.h" NewClass::NewClass(int a, int b) { BaseClass(a+1,b+2); }
Best regards
Bordon
Note: Posted code pieces may not have a good programming style and may not perfect. It is also possible that they do not work in all situations. Code pieces are only indended to explain something particualar.- Als Antwort vorgeschlagen Dimitar DenkovMicrosoft contingent staff, Administrator Dienstag, 13. Oktober 2015 07:49
- Bearbeitet Bordon Dienstag, 13. Oktober 2015 14:42
- Als Antwort markiert Dimitar DenkovMicrosoft contingent staff, Administrator Mittwoch, 4. November 2015 07:57
-
Der Syntax ist so in jedem Fall falsch. Muss heißen:
NewClass::NewClass(int a, int b)
: BaseClass(a+1,b+2); { }
So wie es hier steht wird ein temporäres Objekt erstellt und verworfen und es wir der Default Konstruktor verwendet.Martin Richter -- MVP for VC++ [Germany] -- http://blog.m-ri.de
- Als Antwort vorgeschlagen Dimitar DenkovMicrosoft contingent staff, Administrator Dienstag, 27. Oktober 2015 14:12
- Als Antwort markiert Dimitar DenkovMicrosoft contingent staff, Administrator Mittwoch, 4. November 2015 07:57
Alle Antworten
-
Ganz kann ich Dein Problem jetzt nicht nachvollziehen, wann Du mehr wie 59 Sekunden hast. Aber im CTime Konstruktor gibst Du eine gütltige Zeit an. Und da ist es eben so, dass eine Uhrzeit max. nur 59 Sekunden hat. Mir wäre nicht bekannt wann eine Minute eben mehr wie 60 Sekunden hat.
Wenn Du Zeiten aufaddieren oder abziehen möchtest würde ich Dir empfehmen CTime mit CTimeSpan zu verwenden. Da hatte ich bei solchen Konstrukten wie auf eine bestehende Zeit eine Zeitspanne zu addieren oder subtrahieren nie ein Problem.
Ich bin mir nicht ganz sicher ob ich da Dein Problem getroffen habe, da ich mir nicht sicher bin Deine Essenz verstanden zu haben. Falls ich daneben liege, vilelleicht noch einmal versuchen das mir Dummvogel gaaaaaanz einfach zu erklären.
Best regards
Bordon
Note: Posted code pieces may not have a good programming style and may not perfect. It is also possible that they do not work in all situations. Code pieces are only indended to explain something particualar.- Bearbeitet Bordon Donnerstag, 1. Oktober 2015 10:25
-
Zeit... ich sag's immer wieder... hört auf Zeit in Stunden, Minuten und Sekunden zu messen... Zeit misst man in 100 [ns] Einheiten. Das ist die sogenannte "FILETIME", welche in Windows überall genutzt wird. Und das ist eine 64 bit Zahl. Damit gibt's nie Probleme... wenn du dann was ausgeben willst, kannst du es ja umrechnen lassen (aber das macht man nur, 2 Zeilen vor dem printf oder sonstigen Text-Ausgaben).
PS: aus einem FILETIME (oder auch LARGE_INTEGER) einen 64 bit Wert machen geht wie? -> casten... Bsp:
UINT64 ullTime; ::GetSystemTimeAsFileTime((LPFILETIME)&ullTime);
(der einzige Unterschied zur Nutzung einer FILETIME-struct ist, dass der UINT64 garantiert auf 64 bit aligniert ist, währen FILETIME nur garantiert auf 32 bit aligniert ist... ist also völlig Wurst in dem Fall)
Rudolf
-
Hallo Rudolf
Du hast ja so Recht, nur leider ging's bei mir um die Skalierung eines Diagrammes und hier fängt das Problem schon wieder an. Die Menschen wollen leider Monate, Tage, Stunden und Minuten ablesen und nicht 100ns Einheiten. Und schlimmer noch .. ein Monat hat nicht immer gleich viele Tage!
Ich hab das Problem mittlerweile anders gelöst. Ich hab mir selbst eine Klasse gebastelt, die mit den Systemfunktionen von Stunden, Minuten und Sekunden auf time_t umrechnet und wieder zurück. Und dabei checke ich halt Überläufe in den Sekunden, Minuten, Stunden, Tagen und Monaten. Das ist nicht so einfach, weil jeder Monat unterschiedlich viele Tage hat und es auch Schaltjahre gibt.
Die alte UNIX Größe time_t verwende ich übrigens, weil die Quelldaten nur auf eine Sekunde genau sind, es macht keinen Sinn auf FILETIME zu gehen.
@Bordon: Zeitskalen mit für Menschen sinnvollen Schritteinheiten sind nicht allzu leicht zu machen, weil in jeder Größeneinheit völlig unterschiedliche Schrittweiten relevant sind. Wenn ich auf der Sekundenskala eine Schrittweite von 10Sekunden habe, dann möchte ich ganz einfach den nächsten Wert mit "Altsekunde" + "Schritt" = "Neusekunde" ... und das kann dann schon mal über 60 gehen. Hier könnte ich das noch anders auch machen, aber wenn ich "AltMonat" + "Schritt" = "Neumonat", dann hängt die tatsächliche Schrittweite vom aktuellen Monat ab.
Grüße
FireHeart
-
Hallo Bordon
Eigentlich wollte ich mit diesem Thread ein viel grundsätzlicheres Problem ansprechen:
Angenommen ich habe die Klasse CK1, welche im Konstruktor bereits Daten übernimmt, also:
class CK1 { public: CK1(int param1,int param2); ... private: ... };
Und jetzt will ich aber davon eine Klasse CD1 ableiten, die ebenfalls im Konstruktor Daten übernimmt:
class CD1:public CK1 { public: CD1(int param3,int param4); ... private: ... };
Jetzt kenne ich ja die Methode im Konstruktor, der Basisklasse Daten zu übergeben:
CD1::CD1(int param3,int param4):CK1(param3,param4) { ... }
Was aber, wenn ich nicht param3 und param4 an die Basisklasse übergeben möchte, sondern von param3 und param4 abgewandelte Werte?D.h. ich möchte im Konstruktor der abgeleiteten Klasse erst mal die Übergabewerte für den Konstruktor der Basisklasse berechnen und diesen dann an die Basisklasse übergeben. Geht das überhaupt? Wie sieht die Syntax dazu aus?
Grüße
FireHeart
- Bearbeitet Fire-Heart Donnerstag, 8. Oktober 2015 09:32
-
Direkt geht das nicht, sehe ich auch nicht denn Sinn über die gleichen Parameter was anderes zu machen.
In der abgeleiteten Klasse die Parameter für die Basce Klasse zu ändern könntem an sich hintricksen. Du benötigst halt einen Default Constuctor in der BaseClass, auch wenn Du den nicht explizit aufrufst. Zur not könntest Du den leer lassen.
In Deinem Fall wären virtuelle Konstruktoren das Mittel, die gibt es abern icht in C++...
Zu Deinem Problem wäre der Codeschnipsel vielleicht ein Umweg. Der Default Konstructor würde nur existieren ohne Funktionalität. Je nachdem könnte vielleicht dieser Ansatz Dein Problem lösen, nicht schön, und auch sicher nicht so gedacht, aber wäre ein Ansatz...
------ Base Header ------ class BaseClass { public: BaseClass(); BaseClass(int a, int b); ~BaseClass(void); }; ------ Base Class ------ #include "BaseClass.h" BaseClass::BaseClass() { } BaseClass::BaseClass(int a, int b) { } BaseClass::~BaseClass(void) { } ------ Derived Header ------ #include "baseclass.h" class NewClass : public BaseClass { public: NewClass(int a, int b); ~NewClass(void); }; ------ Derived Class ------ #include "newclass.h" NewClass::NewClass(int a, int b) { BaseClass(a+1,b+2); }
Best regards
Bordon
Note: Posted code pieces may not have a good programming style and may not perfect. It is also possible that they do not work in all situations. Code pieces are only indended to explain something particualar.- Als Antwort vorgeschlagen Dimitar DenkovMicrosoft contingent staff, Administrator Dienstag, 13. Oktober 2015 07:49
- Bearbeitet Bordon Dienstag, 13. Oktober 2015 14:42
- Als Antwort markiert Dimitar DenkovMicrosoft contingent staff, Administrator Mittwoch, 4. November 2015 07:57
-
Der Syntax ist so in jedem Fall falsch. Muss heißen:
NewClass::NewClass(int a, int b)
: BaseClass(a+1,b+2); { }
So wie es hier steht wird ein temporäres Objekt erstellt und verworfen und es wir der Default Konstruktor verwendet.Martin Richter -- MVP for VC++ [Germany] -- http://blog.m-ri.de
- Als Antwort vorgeschlagen Dimitar DenkovMicrosoft contingent staff, Administrator Dienstag, 27. Oktober 2015 14:12
- Als Antwort markiert Dimitar DenkovMicrosoft contingent staff, Administrator Mittwoch, 4. November 2015 07:57
-
Hallo FireHeart,
Ich gehe davon aus, dass Bordons und Martins Antworten Dir weitergeholfen haben. Solltest Du noch Rückfragen dazu haben, gib bitte Bescheid.
Gruß,
DimitarBitte haben Sie Verständnis dafür, dass im Rahmen dieses Forums, welches auf dem Community-Prinzip „IT-Pros helfen IT-Pros“ beruht, kein technischer Support geleistet werden kann oder sonst welche garantierten Maßnahmen seitens Microsoft zugesichert werden können.