operator new only as static member possible?

Discussion in 'C++' started by Ernst Murnleitner, Jan 7, 2004.

  1. Hello Readers,

    Is there a way that only one class can construct a class A and its inherited
    classes A2, A3 etc.?

    I want to construct a class A (and the inherited classes A2, A3 etc.) from a
    (factory) class Fa.
    I wanted to make that only F can call

    new A

    Now, I could make the operator new a private member of A. But in this case I
    would have to declare Fa also as friend for A2, A3 etc.
    If I would use

    protected:
    static void * operator(size_t t);

    all the classes A,A2, A3 also could construct A, A2, A3 ... objects.

    Greetings
    Ernst
     
    Ernst Murnleitner, Jan 7, 2004
    #1
    1. Advertising

  2. Ernst Murnleitner

    John Carson Guest

    "Ernst Murnleitner" <> wrote in message
    news:btgr3v$73uht$-berlin.de
    > Hello Readers,
    >
    > Is there a way that only one class can construct a class A and its
    > inherited classes A2, A3 etc.?
    >
    > I want to construct a class A (and the inherited classes A2, A3 etc.)
    > from a (factory) class Fa.
    > I wanted to make that only F can call
    >
    > new A
    >
    > Now, I could make the operator new a private member of A. But in this
    > case I would have to declare Fa also as friend for A2, A3 etc.
    > If I would use
    >
    > protected:
    > static void * operator(size_t t);
    >
    > all the classes A,A2, A3 also could construct A, A2, A3 ... objects.
    >
    > Greetings
    > Ernst




    I can't tell you how to get exactly what you want, but you can get close.

    1. Define a structure in Fa that is private and declare a static variable of
    that type inside Fa.
    2. Make the constructor of A take a parameter of the private type described
    in 1. This will mean that only Fa and friends of Fa will be able to
    construct A and its derived classes.
    3. Make A and its derived classes friends of Fa. This is necessary if you
    are to define the constructors of A and its derived classes.

    The problem with this scheme is in point 3. Once you make them friends of
    Fa, A and its derived classes will be able to construct objects from the A
    hierarchy. Yet you have to make them friends or else their constructors
    can't be defined.

    But this should not really be a problem. A derived class will only be able
    to construct objects in the A hierarchy if you make that derived class a
    friend of Fa. In that case you are presumably the author of the derived
    class and hence can make sure that it doesn't construct any objects in the A
    hierarchy. By contrast, if a client derives from A, then the derived class
    will not be a friend of Fa and hence will not be able to construct any
    objects in the A hierarchy.

    An example is given below:

    // forward declarations
    class A;
    class A1;
    class A2;


    class Fa
    {
    friend class A;
    friend class A1;
    friend class A2;
    private:
    struct Faprivate{};
    static Faprivate fap;
    public:
    A* MakeA();
    A1* MakeA1();
    A2* MakeA2();
    };

    // definition of static member
    Fa::Faprivate Fa::fap;

    class A
    {
    public:
    A(Fa::Faprivate fap)
    {}
    };


    // Note that the constructor for A1 has a parameter of
    // type Fa::Faprivate even though it would be possible to
    // define a constructor for A1 that took no argument and used
    // Fa's static member Fa::fap in the call to the base class
    // constructor. The parameter is included to stop non-friends
    // of Fa from constructing A1. Similar reasoning applies to A2.


    class A1 : public A
    {
    public:
    A1(Fa::Faprivate fap) : A(fap)
    {}
    };

    class A2 : public A
    {
    public:
    A2(Fa::Faprivate fap) : A(fap)
    {}
    };


    // definitions for Fa's member functions
    A* Fa::MakeA()
    {
    return new A(fap);
    }
    A1* Fa::MakeA1()
    {
    return new A1(fap);
    }
    A2* Fa::MakeA2()
    {
    return new A2(fap);
    }



    int main()
    {
    Fa fa;
    A *pa = fa.MakeA();
    A1*pa1 = fa.MakeA1();
    A2*pa2 = fa.MakeA2();
    return 0;
    }


    --
    John Carson
    1. To reply to email address, remove donald
    2. Don't reply to email address (post here instead)
     
    John Carson, Jan 7, 2004
    #2
    1. Advertising

  3. Ernst Murnleitner

    Chris Theis Guest

    "John Carson" <> wrote in message
    news:...
    > "Robert Frunzke" <> wrote in message
    > news:btgseg$v55$02$-online.com
    > > Ernst Murnleitner wrote:
    > > > Hello Readers,
    > > >
    > > > Is there a way that only one class can construct a class A and its
    > > > inherited classes A2, A3 etc.?
    > > >
    > > > I want to construct a class A (and the inherited classes A2, A3
    > > > etc.) from a (factory) class Fa.
    > > > I wanted to make that only F can call
    > > >
    > > > new A

    > >
    > > You could make the constructor / all constructors private and declare
    > > the factory as a friend.
    > >
    > >
    > >
    > >
    > > Robert

    >
    > That won't work. Consider
    >
    >
    > class A
    > {
    > friend class Fa;
    > private:
    > A()
    > {}
    > };
    >
    > class A1 : public A
    > {
    > };
    >
    > class A2 : public A
    > {
    > };
    >
    > class Fa
    > {
    > public:
    > A* MakeA()
    > {
    > return new A;
    > }
    > A1* MakeA1()
    > {
    > return new A1;
    > }
    > A2* MakeA2()
    > {
    > return new A2;
    > }
    > };
    >
    >
    > int main()
    > {
    > Fa fa;
    > A *pa = fa.MakeA();
    > A1*pa1 = fa.MakeA1();
    > A2*pa2 = fa.MakeA2();
    > return 0;
    > }
    >
    >
    > This won't compile because, even though Fa calls new, the construction of

    a
    > derived class necessarily involves the derived class calling the

    constructor
    > of the base class. If the base class constructor is private, then it

    cannot
    > be called by the derived class.
    >


    So why not use a protected declaration instead of private and the code above
    will work fine. Of course one should also consider how copy ctor and
    assignment op are to be treated because in this version A MyObj(
    *(fa.MakeA()) ); would construct an object of type A.

    Chris
     
    Chris Theis, Jan 7, 2004
    #3
  4. Ernst Murnleitner

    John Carson Guest

    "Chris Theis" <> wrote in message
    news:O1ZKb.3862$
    >
    > So why not use a protected declaration instead of private and the
    > code above will work fine.


    The OP had already considered and rejected this option.

    > Of course one should also consider how
    > copy ctor and assignment op are to be treated because in this version
    > A MyObj(
    > *(fa.MakeA()) ); would construct an object of type A.


    Good point.


    --
    John Carson
    1. To reply to email address, remove donald
    2. Don't reply to email address (post here instead)
     
    John Carson, Jan 8, 2004
    #4
  5. Ernst Murnleitner

    Chris Theis Guest

    "John Carson" <> wrote in message
    news:3ffca938$...
    > "Chris Theis" <> wrote in message
    > news:O1ZKb.3862$
    > >
    > > So why not use a protected declaration instead of private and the
    > > code above will work fine.

    >
    > The OP had already considered and rejected this option.


    Hmm, that must have slipped my attention. Sorry!

    Chris
     
    Chris Theis, Jan 8, 2004
    #5
  6. > 1. Define a structure in Fa that is private and declare a static variable
    of
    > that type inside Fa.
    > 2. Make the constructor of A take a parameter of the private type

    described
    > in 1. This will mean that only Fa and friends of Fa will be able to
    > construct A and its derived classes.
    > 3. Make A and its derived classes friends of Fa. This is necessary if you
    > are to define the constructors of A and its derived classes.


    Thank you. Very good idea. I wanted to avoid to make Factory Fa a friend of
    all A. Your solution only needs to make the A a friend of Fa which seems to
    be more logicall as A do not necessary need to know anything about its
    factory.

    Greetings
    Ernst
     
    Ernst Murnleitner, Jan 8, 2004
    #6
  7. > You'd probably save yourself a lot of hassle by just documenting the
    > fact that one should only make an object from that hierarchy using
    > your factory.
    > It's almost never a good idea to place artificial restrictions on a
    > system, so unless you have a really good reason for this and you're
    > sure that no-one could ever need to create an A object by hand,
    > don't enforce it.


    OK. But the solution of Carson is a relatively easy way to achieve, that a
    certain constructor cannot used by everyone.

    Greetings
    Ernst
     
    Ernst Murnleitner, Jan 8, 2004
    #7
  8. "Ernst Murnleitner" <> wrote in message
    news:btjf7u$7sbbk$-berlin.de...
    | > 1. Define a structure in Fa that is private and declare a static variable
    | of
    | > that type inside Fa.
    | > 2. Make the constructor of A take a parameter of the private type
    | described
    | > in 1. This will mean that only Fa and friends of Fa will be able to
    | > construct A and its derived classes.
    | > 3. Make A and its derived classes friends of Fa. This is necessary if you
    | > are to define the constructors of A and its derived classes.
    |
    | Thank you. Very good idea. I wanted to avoid to make Factory Fa a friend of
    | all A. Your solution only needs to make the A a friend of Fa which seems to
    | be more logicall as A do not necessary need to know anything about its
    | factory.

    How about the following alternative: ?

    class Base
    {
    private:
    class A
    {
    protected:
    friend class Factory;
    A() {}
    public:
    virtual ~A() {}
    virtual void Print() { std::cout << "A" << std::endl; }
    };

    class A1 : public A
    {
    public:
    void Print() { std::cout << "A1" << std::endl; }
    };

    class A2 : public A
    {
    public:
    void Print() { std::cout << "A2" << std::endl; }
    };

    friend class Factory;
    };

    struct Factory : Base::A
    {
    typedef Base::A A;
    typedef Base::A1 A1;
    typedef Base::A2 A2;

    static Base::A* MakeA()
    {
    return new Base::A;
    }

    static Base::A1* MakeA1()
    {
    return new Base::A1;
    }

    static Base::A2* MakeA2()
    {
    return new Base::A2;
    }
    };

    int main()
    {
    Factory::A* Ptr = Factory::MakeA();
    Ptr -> Print(); delete Ptr;

    Ptr = Factory::MakeA1();
    Ptr -> Print(); delete Ptr;

    Ptr = Factory::MakeA2();
    Ptr -> Print(); delete Ptr;

    return 0;
    }

    The main() code is also self documenting, in that you
    can clearly understand, that each object is only being
    instantiated through the 'Factory' class.

    Cheers.
    Chris Val
     
    Chris \( Val \), Jan 8, 2004
    #8
  9. >
    > How about the following alternative: ?
    >
    > class Base
    > {
    > private:
    > class A
    > {
    > protected:
    > friend class Factory;
    > A() {}
    > public:


    I think this would work, but it's an already existing application with 100,
    whereby 50 classes would need this change. Therefore I wouldn't like to
    change it.
     
    Ernst Murnleitner, Jan 12, 2004
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Robert Frunzke
    Replies:
    1
    Views:
    330
    John Carson
    Jan 7, 2004
  2. ghager
    Replies:
    6
    Views:
    623
    ghager
    Jan 19, 2006
  3. dolphin
    Replies:
    3
    Views:
    1,349
    Pete Becker
    Dec 5, 2007
  4. xmllmx
    Replies:
    6
    Views:
    417
    xmllmx
    Feb 3, 2010
  5. W Karas
    Replies:
    3
    Views:
    260
    Victor Bazarov
    Nov 30, 2012
Loading...

Share This Page