Wie könnte man new und delete auf einen Klassenzeiger verbieten



  • pumuckl schrieb:

    Das Umgehen mit Placement New ist dann auch nicht möglich, weil ein operator new reicht, dass der Compiler nicht mehr die globalen op new in Betracht zieht - also auch kein Placement New.

    Bei mir geht das.

    class Test
    {
        void *operator new(size_t size)
        {
            return ::operator new(size);
        }
    
        void operator delete(void *ptr)
        {
            ::operator delete(ptr);
        }
    
        public:
    };
    
    int main()
    {
        Test *c = static_cast<Test*>(malloc(sizeof(Test)));
        c = ::new(c) Test;
        c->~Test();
        free(c);
    }
    


  • Hallo zusammen,

    die Bibliothek ist ziemlich umfangreich, es ist schlicht illusorisch das ganze Konzept über den Haufen zu werfen da:
    - die Bibliothek sehr einfach zu benutzen ist.
    - viele Maschinen bereits Mithilfe dieser Bibliothek erstellt wurden
    - fast alle Konzepte von Scott Meyers erfüllt sind. Ich hatte beim lesen fast bei jedem Tipp ein Deja Vu 😉
    - das kein Mensch bezahlen kann und will.

    Es geht wirklich nur darum meine Objekt Pointer sicher zu machen.

    Der Aufwand muss sich aber in Grenzen halten da ich das aus finanziellen Gründen komplett in meiner Freizeit machen muss.

    Ich glaube ich schau mir mal die Tipps 17, 49..52 nochmal genauer an, eventuell könnten die weiterhelfen.

    Herzliche Grüsse
    Walter



  • wxSkip schrieb:

    Bei mir geht das.

    Mit explizit qualifiziertem globalem new, ja. Aber irgendwo ist dann auch wirklich mal die Grenze zum mutwillig destruktiven Verhalten überschritten - Scheiße bauen kann man immer, z.B. einfach memset auf ein beliebiges Objekt 😉


  • Mod

    pumuckl schrieb:

    wxSkip schrieb:

    Bei mir geht das.

    Mit explizit qualifiziertem globalem new, ja. Aber irgendwo ist dann auch wirklich mal die Grenze zum mutwillig destruktiven Verhalten überschritten - Scheiße bauen kann man immer, z.B. einfach memset auf ein beliebiges Objekt 😉

    Zumindest in generischem Code wäre das durchaus normal. Schließlich kann man sich kaum darauf verlassen, dass bei überladenem new-Operator auch an placement-new gedacht wurde. Beispielsweise ist das Verhalten der construct-Funktion des Standard-Allokator auch mit

    template <class U, class... Args>
    void construct(U* p, Args&&... args);
    12 Effects: ::new((void *)p) U(std::forward<Args>(args)...)
    

    beschrieben.



  • Wie wäre es mit:

    class SaveRootPtr {
       private:
           Root *ptr;
           SaveRootPtr(Root *r): ptr(r) {}
           ~SaveRootPtr() {}
       public:
           // Operator -> und * überladen (habe gerade keine Ahnung wie das geht xD)
           //...
       template <class ObjectType>
       friend SaveRootPtr CreateObject();
    };
    

    Und in createObject dann:

    Root *r=new T();
    return SaveRootPtr(r);
    

    Die Methoden der ObjDB Klasse bekommen dann ein SaveRootPtr als Argument.
    So kann niemand Objekte ohne die createObject Methode erstellen.



  • Ich hab' jetzt nicht alle Antworten gelesen, aber...

    Was spricht nun wirklich dagegen die Konstruktoren und Destruktoren private zu machen?
    Die Factory-Funktion muss irgendwie Zugriff auf Konstruktor und Destruktor haben, aber das lässt sich ja einrichten (z.B. mittels "friend").

    Wenn alle Objekte sowieso zu einem bestimmten Zeitpunkt zerstört werden sollen, und keine Shared-Ownership nötig ist, dann kann man weiterhin einfach mit rohen Zeigern arbeiten.
    new/delete funktionieren dann nimmer, und wenn keine Notwendigkeit besteht manuell new oder delete zu machen, und auch keine das "automatische delete" bei Programmende irgendwie verzögern zu können... dann sollte das doch damit gegessen sein. Oder übersehe ich was?

    p.S.: Die Konstruktoren/Destruktoren der Basisklassen müssen natürlich "protected" gemacht werden statt private. Oder aber die Basisklasse müsste alle abgeleiteten Klassen "kennen", was ... naja etwas komisch wäre.



  • Hallo hustbaer,

    Was spricht nun wirklich dagegen die Konstruktoren und Destruktoren private zu machen?

    Wie Du im PS sagts, geht's nur wenn die ctors und dtors in den Basisklassen nicht privat sondern protected sind.

    Das Bedeutet, die neue Regel lautet "bei allen Instanzierbaren Klassen müssen ctor und dtor Privat sein". Damit habe ich nur die alte Regel "Objekte dürfen nur mit CreateObj() erzeugt und nie mit delete gelöscht werden" mit einer neuen Regel ausgetauscht.

    Rein Gefühlsmässig ist der Verstoss gegen die neue Regel IMHO wahrscheinlicher 😉

    Herzliche Grüsse
    Walter



  • Wenn Du du eine Bibliothek nur für Deppen programmierst, mußt Du Dich nicht wundern, wer sie später nur benutzt.



  • weicher schrieb:

    Hallo hustbaer,

    Was spricht nun wirklich dagegen die Konstruktoren und Destruktoren private zu machen?

    Wie Du im PS sagts, geht's nur wenn die ctors und dtors in den Basisklassen nicht privat sondern protected sind.

    Das Bedeutet, die neue Regel lautet "bei allen Instanzierbaren Klassen müssen ctor und dtor Privat sein". Damit habe ich nur die alte Regel "Objekte dürfen nur mit CreateObj() erzeugt und nie mit delete gelöscht werden" mit einer neuen Regel ausgetauscht.

    Rein Gefühlsmässig ist der Verstoss gegen die neue Regel IMHO wahrscheinlicher 😉

    Herzliche Grüsse
    Walter

    Was willst du jetzt eigentlich damit sagen?
    Soll der Benutzer Stack-Objekte erstellen können? Wenn ja, was spricht dann gegen ein privates new und delete?

    EDIT: Meinst du damit, deine Kollegen würden sich nicht daran halten, Konstruktoren/Destruktoren bei neuen Klassen private/protected zu machen? Das kann man aber relativ einfach nachkorrigieren.



  • weicher schrieb:

    Was spricht nun wirklich dagegen die Konstruktoren und Destruktoren private zu machen?

    Wie Du im PS sagts, geht's nur wenn die ctors und dtors in den Basisklassen nicht privat sondern protected sind.

    Das Bedeutet, die neue Regel lautet "bei allen Instanzierbaren Klassen müssen ctor und dtor Privat sein". Damit habe ich nur die alte Regel "Objekte dürfen nur mit CreateObj() erzeugt und nie mit delete gelöscht werden" mit einer neuen Regel ausgetauscht.

    Rein Gefühlsmässig ist der Verstoss gegen die neue Regel IMHO wahrscheinlicher 😉

    Normalerweise werden seltener eigene Klassen definiert, als irgendwo Objekte erstellt werden.

    Wenn du aber wirklich etwas suchst was automatisch neue abgeleitete Klassen schützt, fürchte ich, kann ich dir nicht helfen. Sowas gibt's in C++ nicht.



  • class Base
    {
       protected:
          struct ErbenMuessenDenKonstruktorProtectedMachen
          {
          };
          Base(ErbenMuessenDenKonstruktorProtectedMachen,...)
          {
             ...
          }
    }
    

Anmelden zum Antworten