Thread: using class as template variable

  1. #1
    Registered User
    Join Date
    Apr 2005
    Posts
    98

    using class as template variable

    i have two classes:

    cls1:
    Code:
    template <typename T> class cls1
    { ... }
    cls2:
    Code:
    class cls2
    { ... }
    and i want to create an object of cls1 of type cls2:
    Code:
    cls1 Object<cls2>;
    but it makes my program crashes.
    i can create Object this way:
    Code:
    cls1 Object<cls2*>
    but it's not very good for me.
    what makes it crash?

  2. #2
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    >> what makes it crash?
    I'd guess that your doing something wrong...like shallow copying cls2 instances.

    If you're not interested in other peoples guesses, then post some code.

    gg

  3. #3
    Registered User
    Join Date
    Apr 2005
    Posts
    98
    well, it's not exactly my code but it has the problem:
    Code:
    template <typename T> class cls1
    {
         protected:
              T* Arr;
         public:
              cls1(T arg)
              {
                   T* tArr = new T[1];
                   Arr[0] = arg;
              }
              ~cls1() { delete[] Arr; }
    };
    
              
    class cls2
    {
         protected:
              char *buffer;
         public:
              cls2() {}
              cls2(char *p)
              {
                   buffer = new char[strlen(p)];
                   strcpy(buffer, p);
              }
              ~cls2() { delete[] buffer; }
    };
    Code:
    cls2 obj("a");
    cls1<cls2> arr(obj);

  4. #4
    carry on JaWiB's Avatar
    Join Date
    Feb 2003
    Location
    Seattle, WA
    Posts
    1,972
    First thing I see:
    Code:
     cls1(T arg)
              {
                   T* tArr = new T[1];
                   Arr[0] = arg;
              }
    You never allocate space for the member variable Arr. And you have a memory leak since you never deallocate tArr...
    "Think not but that I know these things; or think
    I know them not: not therefore am I short
    Of knowing what I ought."
    -John Milton, Paradise Regained (1671)

    "Work hard and it might happen."
    -XSquared

  5. #5
    Registered User
    Join Date
    Apr 2005
    Posts
    98
    oops.. didn't copy it correctly, tArr supposed to be Arr.
    but even when i change it, it crashes.

  6. #6
    Registered User Micko's Avatar
    Join Date
    Nov 2003
    Posts
    715
    change your line
    Code:
    buffer = new char[strlen(p)];
    with
    Code:
    buffer = new char[strlen(p)+1];
    to make room for null character.

    Now observe this
    Code:
    #include <iostream>
    #include <cstring>
    
    using namespace std;
    
    template <typename T> class cls1
    {
         protected:
              T* Arr;
         public:
              cls1(T arg)
              {cout<<"Construct cls1"<<endl;
                   Arr = new T[1];
                   Arr[0] = arg;
                   
              }
              ~cls1() {delete [] Arr; cout<<"Destruct cls1"<<endl;}
              
    };
    
              
    class cls2
    {
         protected:
              char *buffer;
         public:
              cls2() {}
              cls2(char *p)
              {
                   buffer = new char[strlen(p)+1];
                   strcpy(buffer, p);
                   cout<<"Constr. cls2"<<endl;
              }
              ~cls2() {delete[] buffer; cout<<"Destruct cls2"<<endl;}
              cls2(const cls2&){cout<<"Copy constr cls2"<<endl;}
              
    };
    template <class T>
    class test
    {
          T x;
          public: test()
          {
             cout<<"Constr. cls2"<<endl;     
          }
          ~test(){
                  cout<<"Destruct cls2"<<endl;
                  }
    };
    int main()
    {
    
        cls2 obj("amidja");
        cls1<cls2> arr(obj);
    
        cout<<"End of program!"<<endl;
    
    }
    And here's my output:

    Constr. cls2
    Copy constr cls2
    Construct cls1
    Destruct cls2
    End of program
    Destruct cls2
    Destruct cls1
    Destruct cls2

    I think your problem is because you didn't define copy constructor and because of that same memory is deleted more times and this produce crash.
    But there is a little mistery for me, and I hope someone with more experience will help.
    First line:
    Code:
    cls2 obj("amidja");
    will produce call of cls2 constructor.
    Second line
    Code:
    cls1<cls2> arr(obj);
    will produce copy constructor cls2 (expected), cls1 cnstructor (expected) and cls2 destructor(probably because of end of constructor cls1 - arg is going out of scope)
    and at the end of program destructors are called cls2 cls1 and cls2 . I know how to explain cls1 and cls2, and know object that was created by copy constructor needs to be destroyed. But for me there is one destructor cls2 that I cannot explain (maybe it is the one before "end of program", maybe after)

    Let try to solve this together.

    - Micko
    Last edited by Micko; 04-17-2005 at 02:06 PM.
    Gotta love the "please fix this for me, but I'm not going to tell you which functions we're allowed to use" posts.
    It's like teaching people to walk by first breaking their legs - muppet teachers! - Salem

  7. #7
    Registered User Micko's Avatar
    Join Date
    Nov 2003
    Posts
    715
    I think I know what is happening, and I'll try to explain. (if I'm not right please correct me)

    line
    Code:
    cls2 obj("amidja");
    will call cls2 constructor.

    line
    Code:
    cls1<cls2> arr(obj);
    will call copy constructor of class cls2 because of constructor implementation:
    Code:
    cls1(T arg){...
    This acts as ordinary function in which objects are passed by value, and because of that copy constructor of cls2 is called. Also line
    Code:
    Arr = new T[1];
    will call default constructor of cls2
    Then line
    Code:
    cout<<"Construct cls1"<<endl;
    is displayed, and finally at the end of constructor implementation, variable arg which was local to it is destroyed. At this point I can conclude that Arr[0] is not what you expected to be.
    Now, at the end of program destructor there sholud be calls of cls1 first and then cls2 (because of the program stack). Because program destroying object of class1 which contains object of cls2 (Arr[0]) destructor of cls2 is called and then destructor cls1.
    Finaly destructor of cls2 is called for obj beacuse that object is first created.
    I can only advice to you to understand this and reconsider your implementation and take another approach to this.
    I hope this explanation helps!

    - Micko
    Gotta love the "please fix this for me, but I'm not going to tell you which functions we're allowed to use" posts.
    It's like teaching people to walk by first breaking their legs - muppet teachers! - Salem

  8. #8
    Registered User
    Join Date
    Apr 2005
    Posts
    98
    why the line
    Code:
    cls1<cls2> arr(obj);
    calls the copy const. ?
    Last edited by hiya; 04-17-2005 at 02:42 PM.

  9. #9
    Registered User Micko's Avatar
    Join Date
    Nov 2003
    Posts
    715
    Quote Originally Posted by hiya
    why the line
    Code:
    cls1<cls2> arr(obj);
    calls the copy const. ?
    I suggest you to read this!
    Gotta love the "please fix this for me, but I'm not going to tell you which functions we're allowed to use" posts.
    It's like teaching people to walk by first breaking their legs - muppet teachers! - Salem

  10. #10
    Registered User
    Join Date
    Apr 2005
    Posts
    98
    thanks, i understand now =)
    so u don't know how to fix it? =/ coz i don't know any other way to do it

  11. #11
    Registered User Micko's Avatar
    Join Date
    Nov 2003
    Posts
    715
    Well, you should start by defining and implementing copy constructor and operator = to awoid shallow copy. General rule is:
    if your class have pointer that points to memory allocated on the heap you should define copy constructor and assignment operator.

    - Micko
    Gotta love the "please fix this for me, but I'm not going to tell you which functions we're allowed to use" posts.
    It's like teaching people to walk by first breaking their legs - muppet teachers! - Salem

  12. #12
    Senior Member joshdick's Avatar
    Join Date
    Nov 2002
    Location
    Phildelphia, PA
    Posts
    1,146
    I remember that as the Rule of Three.

  13. #13
    Registered User Micko's Avatar
    Join Date
    Nov 2003
    Posts
    715
    That's right joshdick!
    Great link

    - Micko
    Gotta love the "please fix this for me, but I'm not going to tell you which functions we're allowed to use" posts.
    It's like teaching people to walk by first breaking their legs - muppet teachers! - Salem

  14. #14
    Senior Member joshdick's Avatar
    Join Date
    Nov 2002
    Location
    Phildelphia, PA
    Posts
    1,146
    Is the link great enough for a little boost in reputation?
    </whoring>

  15. #15
    Registered User Micko's Avatar
    Join Date
    Nov 2003
    Posts
    715
    It is indeed
    You're very active these days, aren't you.

    - Micko
    Gotta love the "please fix this for me, but I'm not going to tell you which functions we're allowed to use" posts.
    It's like teaching people to walk by first breaking their legs - muppet teachers! - Salem

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 8
    Last Post: 07-24-2006, 08:14 AM
  2. error: template with C linkage
    By michaels-r in forum C++ Programming
    Replies: 3
    Last Post: 05-17-2006, 08:11 AM
  3. Class Template Trouble
    By pliang in forum C++ Programming
    Replies: 4
    Last Post: 04-21-2005, 04:15 AM
  4. include question
    By Wanted420 in forum C++ Programming
    Replies: 8
    Last Post: 10-17-2003, 03:49 AM