Simple inheritance-template question

Discussion in 'C++' started by crea, Apr 14, 2011.

  1. crea

    crea Guest

    I cannot find solution to this:

    Here is the structure:

    template <class T> class Data
    {
    public:
    T p;
    };

    class AA
    {
    public:
    // here I would like to have a data member: m_data
    };

    class BB : public AA
    {
    public:
    };

    If an object is create from AA then I want it to have member data object
    created like this:
    Data<int> m_data;

    But if an object is created from BB then I want:

    Data<string> m_data;

    How to create a member data variable according to what class the object is
    created from? Is this even possible?



    Point is that for BB I want a data member of type "string" and for AA I want
    a data member of type "int". And in both cases the data member name is
    "m_data" and it is located in the class AA.
     
    crea, Apr 14, 2011
    #1
    1. Advertising

  2. crea

    Ian Collins Guest

    On 04/14/11 09:26 PM, crea wrote:
    > I cannot find solution to this:
    >
    > Here is the structure:
    >
    > template<class T> class Data
    > {
    > public:
    > T p;
    > };
    >
    > class AA
    > {
    > public:
    > // here I would like to have a data member: m_data
    > };
    >
    > class BB : public AA
    > {
    > public:
    > };
    >
    > If an object is create from AA then I want it to have member data object
    > created like this:
    > Data<int> m_data;
    >
    > But if an object is created from BB then I want:
    >
    > Data<string> m_data;
    >
    > How to create a member data variable according to what class the object is
    > created from? Is this even possible?


    No, not really. To do so would break the "is a" rule (a BB isn't an
    AA). Maybe make Data a union rather than a template?

    What problem are you trying to solve?

    --
    Ian Collins
     
    Ian Collins, Apr 14, 2011
    #2
    1. Advertising

  3. crea

    crea Guest

    > Point is that for BB I want a data member of type "string" and for AA I
    > want a data member of type "int". And in both cases the data member name
    > is "m_data" and it is located in the class AA.


    So it would look something like this:

    template <class T> class Data
    {
    public:
    T p;
    };

    class AA
    {
    public:
    m_data
    };

    class BB : public AA
    {
    public:
    };

    If I create an object from BB:

    BB b;

    then m_data is created to be string-type (Data class member p becomes
    string)

    And if I create an object from AA

    AA b;

    then m_data is created to be int-type (Data class member p becomes int).

    Not sure if template is best to acquire this. (Actually in my real program
    its not int/string types, but classes where the other one is the parent of
    the other one. So I was first thinking of using inheritance +pointers
    instead of tamplate:

    class Data
    {
    public:
    ParentClass* p;
    };

    and then just set p to point parent and/or its child class object, and
    virtuality would make sure they point to right classes.)




    "crea" <> wrote in message
    news:f5zpp.27551$2...
    >I cannot find solution to this:
    >
    > Here is the structure:
    >
    > template <class T> class Data
    > {
    > public:
    > T p;
    > };
    >
    > class AA
    > {
    > public:
    > // here I would like to have a data member: m_data
    > };
    >
    > class BB : public AA
    > {
    > public:
    > };
    >
    > If an object is create from AA then I want it to have member data object
    > created like this:
    > Data<int> m_data;
    >
    > But if an object is created from BB then I want:
    >
    > Data<string> m_data;
    >
    > How to create a member data variable according to what class the object is
    > created from? Is this even possible?
    >
    >
    >
    >
    >
    >
     
    crea, Apr 14, 2011
    #3
  4. crea

    crea Guest

    "Ian Collins" <> wrote in message
    news:...
    >
    > No, not really. To do so would break the "is a" rule (a BB isn't an AA).
    > Maybe make Data a union rather than a template?


    Thanks, i ll think about this.

    >
    > What problem are you trying to solve?


    Ok, let me put it like it is in my real program:

    Holds the data:
    struct DataHolder
    {

    Data* data;

    };

    Where real Data:
    class Data {...};

    Then I have a class which uses it:

    class AA
    {
    public:
    DataHolder m_data;
    };

    So now I can get hold of the real data from AA by:
    m_data.data;

    Now I want to inherit a class from AA:

    class BB : public AA
    {
    public:
    };

    But for BB I want to use different data -class which is inherited from Data:
    class BBData : public Data
    {...};

    struct DataHolder
    {

    BBData* data;

    };

    class AA
    {
    public:
    DataHolder m_data;
    };

    class BB : public AA
    {
    public:
    };

    So the only thing which should change here is the DataHolder::data s type.
    It looked like a template type problem. But because BBData is inherited from
    Data, maybe virtuality /inheritance could also be used.

    So this should be in DataHolder instead of Data if I create an BB object.
    How to do this? I was thinking using templates first..
     
    crea, Apr 14, 2011
    #4
  5. crea

    crea Guest

    "crea" <> wrote in message
    news:_Lzpp.51518$2...
    >
    > "Ian Collins" <> wrote in message
    > news:...
    >>
    >> No, not really. To do so would break the "is a" rule (a BB isn't an AA).
    >> Maybe make Data a union rather than a template?


    The problem with union would be, that what if want to inherit 100 classes
    later on from AA :). So then I would need to modify this Union 100 times.
    Using inheritance or templates I would not need to add anything. Thats why I
    would prefer to solve this by inheritance or templates. See my other post
    where I describe the problem how it really is.
     
    crea, Apr 14, 2011
    #5
  6. crea

    crea Guest

    One template solution I know, but...

    This would definitely work:
    template <class T> class Data
    {
    public:
    T p;
    };

    template <class T> class AA
    {
    public:
    Data<T> m_data;
    };

    template <class T> class BB : public AA
    {
    public:
    };

    So I could create object like this:

    AA<int> b;
    BB<string> b;

    Ok, this definitely works, but its a bit difficult to put all of those
    templates in all classes. I was thinking that because the only thing I need
    here is that BB has different Data::p type than AA, so it could be done
    hidden in BB class somehow. So there is no need to tell it when calling:

    BB<string> b;

    but rather just:
    BB b;

    I dont think we need to tell the type when creating objects, because the
    classes already know what type it should be (if created an object from BB it
    ALWAYS has string type and AA ALWAYS has int type - thats the situation).
     
    crea, Apr 14, 2011
    #6
  7. crea

    Goran Guest

    On Apr 14, 12:12 pm, "crea" <> wrote:
    > Ok, let me put it like it is in my real program:
    >
    > Holds the data:
    > struct DataHolder
    > {
    >
    >    Data* data;
    >
    > };
    >
    > Where real Data:
    > class Data {...};
    >
    > Then I have a class which uses it:
    >
    > class AA
    > {
    > public:
    > DataHolder m_data;
    >
    > };
    >
    > So now I can get hold of the real data from AA by:
    > m_data.data;
    >
    > Now I want to inherit a class from AA:
    >
    > class BB : public AA
    > {
    > public:
    >
    > };
    >
    > But for BB I want to use different data -class which is inherited from Data:
    > class BBData : public Data
    >  {...};
    >
    > struct DataHolder
    > {
    >
    >    BBData* data;
    >
    > };
    >
    > class AA
    > {
    > public:
    > DataHolder m_data;
    >
    > };
    >
    > class BB : public AA
    > {
    > public:
    >
    > };
    >
    > So the only thing which should change here is the DataHolder::data s type..
    > It looked like a template type problem. But because BBData is inherited from
    > Data, maybe virtuality /inheritance could also be used.
    >
    > So this should be in DataHolder instead of Data if I create an BB object.
    > How to do this? I was thinking using templates first..


    I would simply make sure (through correct coding) that BB does use
    DataHolder that has a pointer to BBData (not "plain" data) and then
    use this:

    class AA
    {
    Data& GetData() { assert(m_data.data); return *m_data.data; }
    }

    class BB : public AA
    {
    BBData& GetData() { return static_cast<BBData&>(AA::GetData(); }
    };

    Goran.
     
    Goran, Apr 14, 2011
    #7
  8. crea

    crea Guest

    "Goran" <> wrote in message
    news:...
    On Apr 14, 12:12 pm, "crea" <> wrote:
    "I would simply make sure (through correct coding) that BB does use
    DataHolder that has a pointer to BBData (not "plain" data) and then
    use this:

    class AA
    {
    Data& GetData() { assert(m_data.data); return *m_data.data; }
    }

    class BB : public AA
    {
    BBData& GetData() { return static_cast<BBData&>(AA::GetData(); }
    };

    Goran."

    I was also thinking that first. But the problem is that inside AA I have
    code like:
    void AA::DoSomething()

    {

    ....(a lot of code)

    m_data.data.Add(new Data());

    ....(a lot of code)

    }



    So if I create a BB object and call this DoSomething , then it will create
    Data-instance and not BBData. I know I could make DoSomething a virtual
    fucntion , but DoSomething is *very* big function so I would rather now copy
    all of it to BB. Yes, I could then create a virtual function for only that
    "Add"... :

    void BB::AddData(..)



    and then have virtual in AA:

    virtual void AA::AddData(..). So now DoSomething becomes:



    void AA::DoSomething()

    {

    ....(a lot of code)

    AddData(..);

    ....(a lot of code)

    }

    but AA has like 5 different this kind of fucntions. Shall I just create a
    virtual function for all of them (5 of them)? I could obviously put them to
    be private. But is there any easier way... this is doable, but needs to
    override many functions.
     
    crea, Apr 14, 2011
    #8
  9. crea

    Goran Guest

    On Apr 14, 1:19 pm, "crea" <> wrote:
    > "Goran" <> wrote in message
    >
    > news:...
    > On Apr 14, 12:12 pm, "crea" <> wrote:
    > "I would simply make sure (through correct coding) that BB does use
    > DataHolder that has a pointer to BBData (not "plain" data) and then
    > use this:
    >
    > class AA
    > {
    >   Data& GetData() { assert(m_data.data); return *m_data.data; }
    >
    > }
    >
    > class BB : public AA
    > {
    >   BBData& GetData() { return static_cast<BBData&>(AA::GetData(); }
    >
    > };
    >
    > Goran."
    >
    > I was also thinking that first. But the problem is that inside AA I have
    > code like:
    > void AA::DoSomething()
    >
    > {
    >
    > ...(a lot of code)
    >
    > m_data.data.Add(new Data());
    >
    > ...(a lot of code)
    >
    > }
    >
    > So if I create a BB object and call this DoSomething , then it will create
    > Data-instance and not BBData. I know I could make DoSomething a virtual
    > fucntion , but DoSomething is *very* big function so I would rather now copy
    > all of it to BB. Yes, I could then create a virtual function for only that
    > "Add"... :
    >
    > void BB::AddData(..)
    > and then have virtual in AA:
    >
    > virtual void AA::AddData(..). So now DoSomething becomes:
    >
    > void AA::DoSomething()
    >
    > {
    >
    > ...(a lot of code)
    >
    > AddData(..);
    >
    > ...(a lot of code)
    >
    > }
    >
    > but AA has like 5 different this kind of fucntions. Shall I just create a
    > virtual function for all of them (5 of them)? I could obviously put them to
    > be private. But is there any easier way... this is doable, but needs to
    > override many functions.


    (Not private, protected, you need to override).

    Overrides seem^^^ to be trivial: create a different object type given
    some parameters, so why not?

    (^^^: I am guessing that after new Data() you actually put something
    useful in that object).

    Goran.
     
    Goran, Apr 14, 2011
    #9
  10. crea

    crea Guest

    "Goran" <> wrote in message
    news:...
    "(Not private, protected, you need to override).

    Overrides seem^^^ to be trivial: create a different object type given
    some parameters, so why not?"

    Yes, this works. Its just that needs to always update both classes if adds
    new code for data. Would be handy to have some kind of template which tells
    the type of data.

    "(^^^: I am guessing that after new Data() you actually put something
    useful in that object)."

    Yes, its data from the file this objects is filled first and then given as
    new parameter.
     
    crea, Apr 14, 2011
    #10
  11. crea

    crea Guest

    "Goran" <> wrote in message
    news:...
    > but AA has like 5 different this kind of fucntions. Shall I just create a
    > virtual function for all of them (5 of them)? I could obviously put them
    > to
    > be private. But is there any easier way... this is doable, but needs to
    > override many functions.


    "(Not private, protected, you need to override).

    Overrides seem^^^ to be trivial: create a different object type given
    some parameters, so why not?

    (^^^: I am guessing that after new Data() you actually put something
    useful in that object)."

    I just checked, and actually the only place where I need some kind of
    virtual calling is when I do this in couple of places:
    m_Data.data.Add(new Data(...));

    So the new -operation needs some kind of virtual version. hmmm , maybe just
    to create a function NewObject:

    in AA:

    virtual Data NewObject()

    { return new Data(); }



    and then have in BB:

    virtual BBData NewObject()

    { return new BBData(); }



    so the call in AA goes now:



    m_Data.data.Add(NewObject());



    What do you think!! Looks like perfect.
     
    crea, Apr 14, 2011
    #11
  12. crea

    crea Guest

    "crea" <> wrote in message
    news:dVBpp.546$2...
    >
    > virtual BBData NewObject()
    >
    > { return new BBData(); }
    >


    Only problem I see here is that the class derived from AA now has to
    remember to create the NewObject fucntion. I they dont, it will fail. Is
    there any way to force the child class to create always this NewObject
    function, otherwise there is compile error? If not, there is a human error
    possibility here if forgets to implement NewObject function in child
    classes.
     
    crea, Apr 14, 2011
    #12
  13. crea

    Goran Guest

    On Apr 14, 2:48 pm, "crea" <> wrote:
    > "crea" <> wrote in message
    >
    > news:dVBpp.546$2...
    >
    >
    >
    > > virtual BBData NewObject()

    >
    > > { return new BBData(); }

    >
    > Only problem I see here is that the class derived from AA now has to
    > remember to create the NewObject fucntion. I they dont, it will fail. Is
    > there any way to force the child class to create always this NewObject
    > function, otherwise there is compile error? If not, there is a human error
    > possibility here if forgets to implement NewObject function in child
    > classes.


    Only if you forget to override __and__ upcast in derived class.

    That's why C++-style casting is there IMO: it stands out like a sore
    thumb, making you think about it more ;-).

    I think you worry too much there. Unless you go completely crazy with
    casting, risk should be quite manageable.

    Goran.
     
    Goran, Apr 14, 2011
    #13
  14. Re: One template solution I know, but...

    On 4/14/2011 6:41 AM, crea wrote:
    > This would definitely work:
    > template<class T> class Data
    > {
    > public:
    > T p;
    > };
    >
    > template<class T> class AA
    > {
    > public:
    > Data<T> m_data;
    > };
    >
    > template<class T> class BB : public AA


    'AA' is missing the template arguments. Won't compile. Did you mean to say

    template<class T> class BB : public AA<T>

    ?

    > {
    > public:
    > };
    >
    > So I could create object like this:
    >
    > AA<int> b;
    > BB<string> b;


    You can't create two objects of different types with the same name in
    the same scope.

    >
    > Ok, this definitely works,


    Nope.

    > but its a bit difficult to put all of those
    > templates in all classes. I was thinking that because the only thing I need
    > here is that BB has different Data::p type than AA, so it could be done
    > hidden in BB class somehow. So there is no need to tell it when calling:
    >
    > BB<string> b;
    >
    > but rather just:
    > BB b;
    >
    > I dont think we need to tell the type when creating objects, because the
    > classes already know what type it should be (if created an object from BB it
    > ALWAYS has string type and AA ALWAYS has int type - thats the situation).
    >
    >


    V
    --
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Apr 14, 2011
    #14
  15. crea

    crea Guest

    Re: One template solution I know, but...

    "Victor Bazarov" <> wrote in message
    news:io6t1k$v7f$...
    > On 4/14/2011 6:41 AM, crea wrote:
    >> This would definitely work:
    >> template<class T> class Data
    >> {
    >> public:
    >> T p;
    >> };
    >>
    >> template<class T> class AA
    >> {
    >> public:
    >> Data<T> m_data;
    >> };
    >>
    >> template<class T> class BB : public AA

    >
    > 'AA' is missing the template arguments. Won't compile. Did you mean to
    > say
    >
    > template<class T> class BB : public AA<T>
    >
    > ?


    yes, sorry... I did not compile the code, so might have errors.

    >
    >> {
    >> public:
    >> };
    >>
    >> So I could create object like this:
    >>
    >> AA<int> b;
    >> BB<string> b;

    >
    > You can't create two objects of different types with the same name in the
    > same scope.


    ye, should be c the other one...

    >
    >>
    >> Ok, this definitely works,

    >
    > Nope.


    after corrections yes.. :)
     
    crea, Apr 14, 2011
    #15
  16. crea

    Noah Roberts Guest

    On 4/14/2011 2:59 AM, crea wrote:
    >> Point is that for BB I want a data member of type "string" and for AA I
    >> want a data member of type "int". And in both cases the data member name
    >> is "m_data" and it is located in the class AA.

    >
    > So it would look something like this:
    >
    > template<class T> class Data
    > {
    > public:
    > T p;
    > };
    >
    > class AA
    > {
    > public:
    > m_data
    > };
    >
    > class BB : public AA
    > {
    > public:
    > };
    >
    > If I create an object from BB:
    >
    > BB b;
    >
    > then m_data is created to be string-type (Data class member p becomes
    > string)
    >
    > And if I create an object from AA
    >
    > AA b;
    >
    > then m_data is created to be int-type (Data class member p becomes int).


    I don't really understand the question so I'll try to answer the various
    questions you could be asking. To override m_data it's as easy as

    class BB : public AA
    {
    public:
    string m_data; // was declared int in AA.
    };

    Now though you have a class with two m_data objects in it depending on
    scope.

    The other thing you seem to be asking is how to declare a member in a
    template based on the instantiation parameter type. This can be done
    two different ways. Luckily, the two ways can be combined nicely:

    template < typename T >
    struct member_type { typedef typename T::mem_t type; };

    template < >
    struct member_type<AA> { typedef int type; };
    template < >
    struct member_type<BB> { typedef string type; };

    template < typename T >
    class Data
    {
    public:
    typedef typename member_type<T>::type m_data_t;
    m_data_t m_data;
    };

    Of course, there's a third option which uses mpl::if_ but it would scale
    as well as a turd.

    --
    http://crazycpp.wordpress.com
     
    Noah Roberts, Apr 14, 2011
    #16
  17. crea

    crea Guest

    "Noah Roberts" <> wrote in message
    news:4da720e7$0$3286$...
    >
    > I don't really understand the question so I'll try to answer the various
    > questions you could be asking. To override m_data it's as easy as
    >
    > class BB : public AA
    > {
    > public:
    > string m_data; // was declared int in AA.
    > };
    >
    > Now though you have a class with two m_data objects in it depending on
    > scope.


    I think you understand my point... I tried this and it works (I actually
    found it myself before, this idea). But is this good programming for sure?
    This is all according to c++ rules to do like this? Because now when we are
    creating a BB-object then int m_data; - member is also created even though
    we never use it for that object. Is this good programming... I am just
    thinking. So there is created one member variable that is never used (int
    m_data; in AA).

    Other than that, this actually would do the job for me.

    My point is that: for objects created from BB I want to have a m_data member
    created with type string:

    Data<string> m_data;

    and for objects created from AA I want a m_data member created with type
    int:

    Data<int> m_data;

    >
    > The other thing you seem to be asking is how to declare a member in a
    > template based on the instantiation parameter type. This can be done two
    > different ways. Luckily, the two ways can be combined nicely:
    >
    > template < typename T >
    > struct member_type { typedef typename T::mem_t type; };
    >
    > template < >
    > struct member_type<AA> { typedef int type; };
    > template < >
    > struct member_type<BB> { typedef string type; };
    >
    > template < typename T >
    > class Data
    > {
    > public:
    > typedef typename member_type<T>::type m_data_t;
    > m_data_t m_data;
    > };
    >


    I think you might be into something here, but this is quite complex for me
    so takes some time to understand this code :). I ll let you know. This might
    be even better than your first suggestion because we would not create a
    variable which is never used.


    > Of course, there's a third option which uses mpl::if_ but it would scale
    > as well as a turd.
     
    crea, Apr 15, 2011
    #17
  18. crea

    crea Guest


    > The other thing you seem to be asking is how to declare a member in a
    > template based on the instantiation parameter type. This can be done two
    > different ways. Luckily, the two ways can be combined nicely:
    >
    > template < typename T >
    > struct member_type { typedef typename T::mem_t type; };
    >
    > template < >
    > struct member_type<AA> { typedef int type; };
    > template < >
    > struct member_type<BB> { typedef string type; };
    >
    > template < typename T >
    > class Data
    > {
    > public:
    > typedef typename member_type<T>::type m_data_t;
    > m_data_t m_data;
    > };
    >


    Can you then also show my how to use this (in main function)? I am a bit
    lost , because seems like its not exatcly the same as my example.
     
    crea, Apr 17, 2011
    #18
    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. Chris Theis
    Replies:
    2
    Views:
    480
    Chris Theis
    Jul 24, 2003
  2. tom_usenet
    Replies:
    0
    Views:
    539
    tom_usenet
    Jul 24, 2003
  3. Replies:
    1
    Views:
    2,114
    Gianni Mariani
    Jun 8, 2007
  4. Peng Yu
    Replies:
    3
    Views:
    781
    Thomas J. Gritzan
    Oct 26, 2008
  5. nguillot
    Replies:
    5
    Views:
    532
Loading...

Share This Page