Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 8 of 8
  1. #1
    Regular Coder brad211987's Avatar
    Join Date
    Sep 2005
    Location
    Ohio
    Posts
    631
    Thanks
    10
    Thanked 50 Times in 50 Posts

    C++ redefinition of class

    Brushing up on C++ for a class and started in a new text book with some of the basic exercises. This particular one is to implement a Custom String class using primitive strings. I've created a class named MyString, a header file for it, and a test file that uses it. My problem is that when I compile, i get an error saying
    MyString.cpp:3: error: redefinition of ‘class MyString’
    MyString.h:5: error: previous definition of ‘class MyString’
    I have included the header guards in my header file to prevent this, but I've obviously missed a beat somewhere as it is not working for me. Any ideas on what I've missed here? I've looked at examples of defining header files for classes and using header guards, but haven't been able to find out what I am missing yet.

    Here is the code I'm working with so far, none of the member functions are implemented as I am just trying to get to a project that compiles to start with.

    MyString.h
    Code:
    #ifndef MYSTRING_H
    #define MYSTRING_H
    
    class MyString
    {
        private:
            char * storedValue;
        public:    
            MyString();
            MyString(const MyString&);
            MyString(char * str);
            int length();
            void resize(int n, char c);
            void clear();
            bool empty();
            void insert(int pos1, const MyString& str);
            void insert(int pos1, const char* s);
            void erase(int pos, int n);
            int find(const MyString& str);
            int find(const char* s);
            int compare( const MyString& str);
            int compare(const char* s);
            char* getStr();
    };
    #endif
    MyString.cpp
    Code:
    #include "MyString.h"
    
    class MyString
    {
        private:
            char * storedValue ;
        
        public:
        ~MyString()
        {
            delete storedValue;
        }//end destructor
        
        const MyString & operator=(const MyString & str)
        {
            if (this != &str)
                storedValue = str.storedValue;
            
            return *this;
        }//end operator method
        
        MyString(const MyString & str) : storedValue(str.storedValue)
        {
        }//end copy constructor
        
        MyString(char * str)
        {
            storedValue = str;
        }//end constructor MyString
        
        MyString()
        {
            storedValue = '\0';
        }//end constructor MyString
        
        int length()
        {
            
        }//end member function length
        
        void resize(int n, char c)
        {
            
        }//end member function resize
        
        void clear()
        {
            
        }//end member function clear
        
        bool empty()
        {
            return true;
        }//end member function empty
        
        void insert(int pos1, const MyString& str)
        {
            
        }//end member function insert
        
        void insert(int pos1, const char* s)
        {
            
        }//end member function insert
        
        void erase(int pos, int n)
        {
            
        }//end member function erase
        
        int find(const MyString& str)
        {
            return 1;
        }//end member function find
        
        int find(const char* s)
        {
            return 1;
        }//end member function find
        
        int compare( const MyString& str)
        {
            return 1;
        }//end member function compare
        
        int compare(const char* s)
        {
            return 1;
        }//end member function compare
        
        char* getStr()
        {
            return storedValue;
        }//end member function getStr
    };//end class MyString
    test.cpp
    Code:
    #include <iostream> 
    #include "MyString.h" 
    using namespace std; 
     
    int main(void) 
    { 
      MyString i="This is my string"; 
      cout << "The value of i: \'" << i.getStr() << "\' and the length is: " << i.length() <<endl;
      return 0;  
    }

  • #2
    Rockstar Coder
    Join Date
    Jun 2002
    Location
    USA
    Posts
    9,074
    Thanks
    1
    Thanked 328 Times in 324 Posts
    The problem is in your cpp, you are declaring another class. Member functions aren't defined that way.

    As an example of how you would do it:
    Code:
    const MyString & MyString::operator=(const MyString & str)
        {
            if (this != &str)
                storedValue = str.storedValue;
            
            return *this;
        }//end operator method
    You don't need the class declaration or any access specifiers.
    OracleGuy

  • Users who have thanked oracleguy for this post:

    brad211987 (09-08-2009)

  • #3
    Regular Coder brad211987's Avatar
    Join Date
    Sep 2005
    Location
    Ohio
    Posts
    631
    Thanks
    10
    Thanked 50 Times in 50 Posts
    Ok, if I understand correctly.......Since I've declared the class and access specifiers in my header file, I will not need them at all in my CPP file, but instead should prefix my member function names with MyString:: to specify that they are part of the class defined in the header file? If I have it right, that makes sense. Will give it a try after work today then.

  • #4
    Rockstar Coder
    Join Date
    Jun 2002
    Location
    USA
    Posts
    9,074
    Thanks
    1
    Thanked 328 Times in 324 Posts
    Quote Originally Posted by brad211987 View Post
    Ok, if I understand correctly.......Since I've declared the class and access specifiers in my header file, I will not need them at all in my CPP file, but instead should prefix my member function names with MyString:: to specify that they are part of the class defined in the header file? If I have it right, that makes sense. Will give it a try after work today then.
    Yes, that is correct.
    OracleGuy

  • #5
    Regular Coder brad211987's Avatar
    Join Date
    Sep 2005
    Location
    Ohio
    Posts
    631
    Thanks
    10
    Thanked 50 Times in 50 Posts
    Thanks! I have it working now. Taking a little bit of effort to adjust to c++ after 5 years of mostly java.

  • #6
    Regular Coder brad211987's Avatar
    Join Date
    Sep 2005
    Location
    Ohio
    Posts
    631
    Thanks
    10
    Thanked 50 Times in 50 Posts
    I'm back with a new issue. I am getting some sort of a memory error, that I believe is something I am doing wrong when creating my string pointer.

    Here is the error:
    *** glibc detected *** ./test2: munmap_chunk(): invalid pointer: 0x0000000000400acd ***
    ======= Backtrace: =========
    /lib/libc.so.6[0x7fc89610acb8]
    ./test2[0x400944]
    ./test2[0x4009d7]
    /lib/libc.so.6(__libc_start_main+0xe6)[0x7fc8960b15a6]
    ./test2[0x4006a9]
    ======= Memory map: ========
    00400000-00401000 r-xp 00000000 07:00 408868 /home/brad/project1/test2
    00601000-00602000 r--p 00001000 07:00 408868 /home/brad/project1/test2
    00602000-00603000 rw-p 00002000 07:00 408868 /home/brad/project1/test2
    01d65000-01d86000 rw-p 01d65000 00:00 0 [heap]
    7fc896093000-7fc8961fb000 r-xp 00000000 07:00 809463 /lib/libc-2.9.so
    7fc8961fb000-7fc8963fb000 ---p 00168000 07:00 809463 /lib/libc-2.9.so
    7fc8963fb000-7fc8963ff000 r--p 00168000 07:00 809463 /lib/libc-2.9.so
    7fc8963ff000-7fc896400000 rw-p 0016c000 07:00 809463 /lib/libc-2.9.so
    7fc896400000-7fc896405000 rw-p 7fc896400000 00:00 0
    7fc896405000-7fc89641b000 r-xp 00000000 07:00 809485 /lib/libgcc_s.so.1
    7fc89641b000-7fc89661b000 ---p 00016000 07:00 809485 /lib/libgcc_s.so.1
    7fc89661b000-7fc89661c000 r--p 00016000 07:00 809485 /lib/libgcc_s.so.1
    7fc89661c000-7fc89661d000 rw-p 00017000 07:00 809485 /lib/libgcc_s.so.1
    7fc89661d000-7fc8966a1000 r-xp 00000000 07:00 809496 /lib/libm-2.9.so
    7fc8966a1000-7fc8968a0000 ---p 00084000 07:00 809496 /lib/libm-2.9.so
    7fc8968a0000-7fc8968a1000 r--p 00083000 07:00 809496 /lib/libm-2.9.so
    7fc8968a1000-7fc8968a2000 rw-p 00084000 07:00 809496 /lib/libm-2.9.so
    7fc8968a2000-7fc896993000 r-xp 00000000 07:00 494091 /usr/lib/libstdc++.so.6.0.10
    7fc896993000-7fc896b93000 ---p 000f1000 07:00 494091 /usr/lib/libstdc++.so.6.0.10
    7fc896b93000-7fc896b9a000 r--p 000f1000 07:00 494091 /usr/lib/libstdc++.so.6.0.10
    7fc896b9a000-7fc896b9c000 rw-p 000f8000 07:00 494091 /usr/lib/libstdc++.so.6.0.10
    7fc896b9c000-7fc896baf000 rw-p 7fc896b9c000 00:00 0
    7fc896baf000-7fc896bcf000 r-xp 00000000 07:00 809443 /lib/ld-2.9.so
    7fc896dae000-7fc896db1000 rw-p 7fc896dae000 00:00 0
    7fc896dcb000-7fc896dce000 rw-p 7fc896dcb000 00:00 0
    7fc896dce000-7fc896dcf000 r--p 0001f000 07:00 809443 /lib/ld-2.9.so
    7fc896dcf000-7fc896dd0000 rw-p 00020000 07:00 809443 /lib/ld-2.9.so
    7fff9edba000-7fff9edcf000 rw-p 7ffffffea000 00:00 0 [stack]
    7fff9edfe000-7fff9edff000 r-xp 7fff9edfe000 00:00 0 [vdso]
    ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
    Aborted

    Here is the CPP class, snipped out all but the constructors:
    Code:
    #include "MyString.h"
    #include <string.h>
        char * storedValue ;
        
        MyString::~MyString()
        {
            delete storedValue;
        }//end destructor
    
        const MyString & MyString::operator=(const MyStri09ng & str)
        {
            if (this != &str)
                storedValue = str.storedValue;
            
            return *this;
        }//end operator method
        
        MyString::MyString(const MyString & str) : storedValue(str.storedValue)
        {
        }//end copy constructor
        
        MyString::MyString(char * str)
        {
            storedValue = str;
        }//end constructor MyString
        
        MyString::MyString()
        {
            storedValue = "";
        }//end constructor MyString
    }
    And here is my snippet of test code that does nothing but create the string for now:
    Code:
    #include <iostream>
    #include "MyString.h"
    using namespace std;
    
    int main(void)
    {
        MyString i="This is my string";
        //cout << "The value of i: \'" << i.getStr() << "\' and the length is: " << i.length() <<endl; 
        
        //i.clear();
        
        ///cout << "length is now: " << i.length() << endl;
        //cout << "empty? " << i.empty() << endl;
        
        return 0;
    }
    I commented out the rest of the code in the test program so that I could isolate where my issue is. This is what leads me to think it is a problem in the constructors. I downloaded the valgrind tool, never used it before but here is what it gave me:

    ==5131== Memcheck, a memory error detector.
    ==5131== Copyright (C) 2002-2008, and GNU GPL'd, by Julian Seward et al.
    ==5131== Using LibVEX rev 1884, a library for dynamic binary translation.
    ==5131== Copyright (C) 2004-2008, and GNU GPL'd, by OpenWorks LLP.
    ==5131== Using valgrind-3.4.1-Debian, a dynamic binary instrumentation framework.
    ==5131== Copyright (C) 2000-2008, and GNU GPL'd, by Julian Seward et al.
    ==5131== For more details, rerun with: -v
    ==5131==
    ==5131== Invalid free() / delete / delete[]
    ==5131== at 0x4C260AD: operator delete(void*) (vg_replace_malloc.c:342)
    ==5131== by 0x400943: MyString::~MyString() (in /home/brad/project1/test2)
    ==5131== by 0x4009D6: main (in /home/brad/project1/test2)
    ==5131== Address 0x400acd is not stack'd, malloc'd or (recently) free'd
    ==5131==
    ==5131== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 8 from 1)
    ==5131== malloc/free: in use at exit: 0 bytes in 0 blocks.
    ==5131== malloc/free: 0 allocs, 1 frees, 0 bytes allocated.
    ==5131== For counts of detected errors, rerun with: -v
    ==5131== All heap blocks were freed -- no leaks are possible.
    Any advice is greatly appreciated. Should I be in some way deleting old memory when creating the initial reference to my strings in the constructors? I've tried what I thought would do that but didn't have any different results. What I tried was:

    Code:
    char* org = storedValue;
    storedValue = "";
    delete org;
    On a side note, can anyone recommend a decent text book for c++? I'm not too satisfied with the level of detail in the one I have.

  • #7
    Rockstar Coder
    Join Date
    Jun 2002
    Location
    USA
    Posts
    9,074
    Thanks
    1
    Thanked 328 Times in 324 Posts
    You are doing what is called a shallow copy in your constructors and assignment operator. You need to do a deep copy.

    Shallow copy:
    Code:
    MyString::MyString(char * str)
    {
         storedValue = str;
    }
    Deep copy:
    Code:
    MyString::MyString(char * str)
    {
         storedValue = new char[strlen(str) + 1];
         strcpy(storedValue, str);
    }
    The reason for the difference is that in a shallow copy, the string is pointing to the whatever is passed in. So if that pointer goes away, the pointer in your string class will be invalid.

    You need to fix the rest of the constructors and your assignment operator in a similar fashion. Does that make sense?

    Also let me see your header file, why is char * storedValue ; in your CPP? If there is a variable called that in your class, that storedValue declaration in your cpp isn't being used.

    Code:
    char* org = storedValue;
    storedValue = "";
    delete org;
    This isn't how pointers work. When you assign a string literal to a pointer, you can't delete it. Because that string literal is on the stack, not the heap. You only delete memory created on the heap with the 'new' command.
    Last edited by oracleguy; 09-09-2009 at 03:31 PM.
    OracleGuy

  • Users who have thanked oracleguy for this post:

    brad211987 (09-09-2009)

  • #8
    Regular Coder brad211987's Avatar
    Join Date
    Sep 2005
    Location
    Ohio
    Posts
    631
    Thanks
    10
    Thanked 50 Times in 50 Posts
    Thanks again! Memory issues are resolved, and I took the storedValue declaration out of the CPP file, as it is already in the header file. Learned more from your few posts than 5 chapters of "C++ for Java Programmers". Not a book I would recommend for someone learning C++ in depth after learning other languages for a long time. I think a trip to the bookstore is in my future.


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •