none
Data member of a class contains instance of another class

    Question

  • hai,

    I have 2 classes. first class with 2 static member function and second one is pure virtual class.

     

    instance of pure virtual class are need to be stored by one method of first class.

     

    Another method of first class can call the virtual function by using the object holded(obj.vir fn() ) in other method of this call.

     

    can anybody can halp to find the solution for this problem (How to do).

     

    thanks in advance.

    Thursday, November 22, 2007 9:15 AM

Answers

  •  

    hi nagira,

     

     

    First of all there is nothing like pure virtual class.i assume that you might be refering to an abstract class.

    I guess you can follow singleton design approach to store the class instance as your datamember.

    In the first class header file, declare a pointer to second class.( SecondClass* pSc) and

    update the pointer when the second class is instantiated for the first time.

     

     

     

    Thursday, November 22, 2007 10:06 AM
  •  

    hai Blue,

     

    Thankyou for your reply,

     

    I meant the abstract class only.

     

    ok. I will have a singleton class. I need this class with 2 static methods.

     

    one method has to store the instance of abstract class. with that object the next method has to call the virtual function.

     

    here my pbm is How can I  interact between these two classes.

     

    First class                                        Second class(derived)

    -------------                                          -------------------

    oneMethod()                                           virtual fn()

       call virtual fn()

     

    secondMethod()

       holds abstract class(Base) objects

     

     

    thans in advance

     

    Regards,

    Nagira

    Thursday, November 22, 2007 11:25 AM
  • hi,

     

    I have created object pointer for the second class in the first class.

     

    I have updated it with second class object.

     

    how I ensure it holds list of second class object. Because For each instance os second class, the other method has to call virtual function of second class.

     

    What data type I have to maintain for holding objects?

     

    If the expalnation is not clear, I'll exp clearly.

     

    thank you,

     

    Regards,

    Nagira

    Friday, November 23, 2007 10:47 AM
  • when I said SINGLETON, that means there can always be only one instance of second class by means of which you can call the required function.

     

    class Second

    {

    private:

    //member variable to hold the instance

    static Second* m_pSecondClassInstance;

     

    public:

    static Second* GetSecondClassInstance();

     

    private:

    //make your constructor private so that you can avoid multiple instances

    Second();

    }

     

     

    Second* Second ::GetSecondClassInstance()

    {

    //check if instance is already been created

    if(m_pSecondClassInstance== NULL)

    {

    //create the instance if it is not created else return the existing created one

    m_pSecondClassInstance = new Second();

    return m_m_pSecondClassInstance;

    }

    else

    {

    return m_pSecondClassInstance;

    }

    }

     

    you can always refer to this instance from any class by calling Second::GetSecondClassInstance() since its a static member.

     

    hope i am clear now

    Friday, November 23, 2007 11:19 AM
  •  bluesaphire wrote:

    Second* Second ::GetSecondClassInstance()

    {

    //check if instance is already been created

    if(m_pSecondClassInstance== NULL)

    {

    //create the instance if it is not created else return the existing created one

    m_pSecondClassInstance = new Second();

    return m_m_pSecondClassInstance;

    }

    else

    {

    return m_pSecondClassInstance;

    }

    }


    Just as a side note...this singleton can only be used in a single-threaded environment...in a multi-thread one you can experience race conditions or memory leaks for example:


    If two threads are accessing the singleton 'GetSecondClassInstance()' function, the following might happen:

    • Thread A will check 'm_pSecondClassInstance' and find it being 0 and will enter the body
    • A context-switch happens and thread B will also check 'm_pSecondClassInstance' and find it being 0 and will enter the body as well
    • Thread B will create one instance of the class 'Second' and leave the body
    • A context-switch happens and thread A will create another instance of 'Second', thus, overwriting the previous assigned address of 'm_pSecondClassInstance'
    Thus....the first one will never be released...


    In order to avoid these scenarios, you need to provide some locking mechanism. However, if you place the critical section (or any other locking object) at the top, then you would add the overhead of entering the critical section every time, aclient wants to get the singleton instance - even if it is already created.


    class Singleton

    {

    public:

      static Singleton* instance()

      {

        // Get locking object

        if(!instance_)

          instance_ = new Singleton;


        return instance_;

      }


    private:

      static Singleton* instance_;

    };



    If you look at this code, it should be clear that the locking object is called every time you call the function 'instance()'. This is of course not necessary, since the critical point here is only the creation of the singleton the first time. Since locking object are kernel objects, there is a lot involved here...

    Thus, you rather do the locking after the check...thus


    class Singleton

    {

    public:

      static Singleton* instance()

      {

        if(!instance_)

        {

          // Get locking object

          instance_ = new Singleton;

        }


        return instance_;

      }


    private:

      static Singleton* instance_;

    };



    Better...but...unfortunately only for single-threaded applications. Although we solved the problem of having to lock every time we call the function, we again introduced the multi-threaded problem mentioned earlier...

    The solution to this is the use of the double-checked locking mechanism...which would lead to the following...


    class Singleton

    {

    public:

      static Singleton* instance()

      {

        if(!instance_)

        {

          // Get locking object


          // Double-check

          if(!instance_)

            instance_ = new Singleton;

        }


        return instance_;

      }


    private:

      static Singleton* instance_;

    };



    Now, we have achieved our goal...this way, the creation of the singleton is locked against multithreading and unnecessary locking calls are avoided...


    Disclaimer: There are some potential issues with the double-checked locking mechanism however, they are beyond the scope of this question.


    I apologize for getting a little bit off-topic here however, i have seen many developers spending hours of trying to find problems caused by singletons that are not truly singletons.... 

    Friday, November 23, 2007 3:51 PM

All replies

  •  

    hi nagira,

     

     

    First of all there is nothing like pure virtual class.i assume that you might be refering to an abstract class.

    I guess you can follow singleton design approach to store the class instance as your datamember.

    In the first class header file, declare a pointer to second class.( SecondClass* pSc) and

    update the pointer when the second class is instantiated for the first time.

     

     

     

    Thursday, November 22, 2007 10:06 AM
  •  

    hai Blue,

     

    Thankyou for your reply,

     

    I meant the abstract class only.

     

    ok. I will have a singleton class. I need this class with 2 static methods.

     

    one method has to store the instance of abstract class. with that object the next method has to call the virtual function.

     

    here my pbm is How can I  interact between these two classes.

     

    First class                                        Second class(derived)

    -------------                                          -------------------

    oneMethod()                                           virtual fn()

       call virtual fn()

     

    secondMethod()

       holds abstract class(Base) objects

     

     

    thans in advance

     

    Regards,

    Nagira

    Thursday, November 22, 2007 11:25 AM
  • hi,

     

    I have created object pointer for the second class in the first class.

     

    I have updated it with second class object.

     

    how I ensure it holds list of second class object. Because For each instance os second class, the other method has to call virtual function of second class.

     

    What data type I have to maintain for holding objects?

     

    If the expalnation is not clear, I'll exp clearly.

     

    thank you,

     

    Regards,

    Nagira

    Friday, November 23, 2007 10:47 AM
  • when I said SINGLETON, that means there can always be only one instance of second class by means of which you can call the required function.

     

    class Second

    {

    private:

    //member variable to hold the instance

    static Second* m_pSecondClassInstance;

     

    public:

    static Second* GetSecondClassInstance();

     

    private:

    //make your constructor private so that you can avoid multiple instances

    Second();

    }

     

     

    Second* Second ::GetSecondClassInstance()

    {

    //check if instance is already been created

    if(m_pSecondClassInstance== NULL)

    {

    //create the instance if it is not created else return the existing created one

    m_pSecondClassInstance = new Second();

    return m_m_pSecondClassInstance;

    }

    else

    {

    return m_pSecondClassInstance;

    }

    }

     

    you can always refer to this instance from any class by calling Second::GetSecondClassInstance() since its a static member.

     

    hope i am clear now

    Friday, November 23, 2007 11:19 AM
  •  bluesaphire wrote:

    Second* Second ::GetSecondClassInstance()

    {

    //check if instance is already been created

    if(m_pSecondClassInstance== NULL)

    {

    //create the instance if it is not created else return the existing created one

    m_pSecondClassInstance = new Second();

    return m_m_pSecondClassInstance;

    }

    else

    {

    return m_pSecondClassInstance;

    }

    }


    Just as a side note...this singleton can only be used in a single-threaded environment...in a multi-thread one you can experience race conditions or memory leaks for example:


    If two threads are accessing the singleton 'GetSecondClassInstance()' function, the following might happen:

    • Thread A will check 'm_pSecondClassInstance' and find it being 0 and will enter the body
    • A context-switch happens and thread B will also check 'm_pSecondClassInstance' and find it being 0 and will enter the body as well
    • Thread B will create one instance of the class 'Second' and leave the body
    • A context-switch happens and thread A will create another instance of 'Second', thus, overwriting the previous assigned address of 'm_pSecondClassInstance'
    Thus....the first one will never be released...


    In order to avoid these scenarios, you need to provide some locking mechanism. However, if you place the critical section (or any other locking object) at the top, then you would add the overhead of entering the critical section every time, aclient wants to get the singleton instance - even if it is already created.


    class Singleton

    {

    public:

      static Singleton* instance()

      {

        // Get locking object

        if(!instance_)

          instance_ = new Singleton;


        return instance_;

      }


    private:

      static Singleton* instance_;

    };



    If you look at this code, it should be clear that the locking object is called every time you call the function 'instance()'. This is of course not necessary, since the critical point here is only the creation of the singleton the first time. Since locking object are kernel objects, there is a lot involved here...

    Thus, you rather do the locking after the check...thus


    class Singleton

    {

    public:

      static Singleton* instance()

      {

        if(!instance_)

        {

          // Get locking object

          instance_ = new Singleton;

        }


        return instance_;

      }


    private:

      static Singleton* instance_;

    };



    Better...but...unfortunately only for single-threaded applications. Although we solved the problem of having to lock every time we call the function, we again introduced the multi-threaded problem mentioned earlier...

    The solution to this is the use of the double-checked locking mechanism...which would lead to the following...


    class Singleton

    {

    public:

      static Singleton* instance()

      {

        if(!instance_)

        {

          // Get locking object


          // Double-check

          if(!instance_)

            instance_ = new Singleton;

        }


        return instance_;

      }


    private:

      static Singleton* instance_;

    };



    Now, we have achieved our goal...this way, the creation of the singleton is locked against multithreading and unnecessary locking calls are avoided...


    Disclaimer: There are some potential issues with the double-checked locking mechanism however, they are beyond the scope of this question.


    I apologize for getting a little bit off-topic here however, i have seen many developers spending hours of trying to find problems caused by singletons that are not truly singletons.... 

    Friday, November 23, 2007 3:51 PM
  • hai,

     

    I have created singleton class.

     

    Code Block

    /// singleton class

    class Logger

    {

    private:

     

    static int nCount;

    static int nMaxInstance;

     

    Logger()

    {

    }

    public:

    ~Logger()

    {

    -- nCount; // delete pObj;

    }

    static BaseLogWriter *string;

     

    static Logger* CreateInstance();

    static void WriteToLog(char *str)

    {

        string->WriteLine("hello");

    }

    static void AddLogger(BaseLogWriter *pt)

    {

    string = pt;

    }

    };

    BaseLogWriter *Logger::string=new LogWriter;

     

    int Logger::nCount =0;

    int Logger::nMaxInstance = 1;

    Logger* Logger::CreateInstance()

    {

    Logger *ptr = NULL;

    if (nMaxInstance > nCount )

    {

    ptr = new Logger;

    ++ nCount;

    }

    return ptr;

    }

    ////////////////////////////////////////////////////////////// abstract class ///////////////////////////////////////////

    class BaseLogWriter

    {

    public:

    BaseLogWriter()

    {

    }

    ~BaseLogWriter()

    {

    }

    virtual void WriteLine(char *a)=0;

    };

    ////////////////////////////////// child - Virtual Class /////////////////////////////////

    class BaseLogWriter

    {

    public:

    BaseLogWriter()

    {

    }

    ~BaseLogWriter()

    {

    }

    virtual void WriteLine(char *a)=0;

    };

     

    class LogWriter:public BaseLogWriter

    {

    public:

    LogWriter(){}

    ~LogWriter(){}

    void WriteLine(char *a)

    {

    printf("in child of pure virtaul function%s\n", a);

    using std::fstream;

    fstream fp;

    fp.open("D:\\log.txt",ios::out);

    fp<<a;

    }

    };

     

     

     

     

    Here, Logger class should have an array, map,or other such structure which contains instances of BaseLogWriter classes.

     

    To add a BaseLogWriter to AddLogger method, we call Logger::AddLogger ( BaseLogWriter *pt)

     

    Therefore Logger should have a method AddLogger which is called to add BaseLogWriter instances to it.  Each time a class (a call from outside class) tells Logger to log something, Logger then deligates the logging task to all the LogWriter instances what are registered with it.

     

    If the instance is added to AddLogger, WriteToLog take that instance to call WriteLine(char *) method of abstract class.

     

    Each time Logger::WriteToLog is called, BaseLogWriter instance will actually write a line to a file

     

    here my doubt is, How shall I maintain an array that holds list of BaseLogWriter obbjects.

     

    In the above code, it is developed for holding single object. Have I done it correctly?. If any changes please tell. This project is for logging purpose.

     

    please help

     

    Regards,

    Nagira

     

    Saturday, November 24, 2007 9:01 AM