0

Let's take this snippet code :

class MyClass
{
public:
    int m_num;
    MyClass(int n) { m_num = n;}
}

If I create an object of this class the following way :

MyClass mc1(5);
MyClass mc2(mc1);

This calls to the default copy-constructor and it'll automatically assign mc2.m_num = mc1.m_num ? Also if there's a call inside the class which makes an instance the following way :

MyClass mc3(*this);

This will call to the default copy-constructor same as with mc2 the *this is just getting the object itself to be copied ?

Second problem I'm having is with compiling my code with Microsoft Visual Studio 2013. I've made a String class and when I try to compile I get lot's of linking error telling me that the functions are already defined for some reason. String.h :

#pragma once
class String
{
private:
    char* m_szStr;
    unsigned int m_length;
public:
    String(const char*);
    explicit String(unsigned int);
    String(const String&);
    ~String();
    String& operator=(const String&);
    bool operator==(const String&) const;
    String operator+(const String&) const;
    operator const char*() const;
    int findStr(char*) const;
    int getLen() const;
    void copyStr(const char*);

};

String.cpp:

#include "stdafx.h"
#include "String.h"

String::String(const char* pch)
{
    m_szStr = NULL;
    copyStr(pch);
}

String::String(unsigned int len)
{
    m_length = len;
    m_szStr = new char[m_length];
}

String::String(const String& that)
{
    copyStr(that.m_szStr);
}

String::~String()
{
    delete[] m_szStr;
}

String& String::operator=(const String& that)
{
    copyStr(that.m_szStr);
    return *this;
}

bool String::operator==(const String& that) const
{

    if (m_length != that.m_length)
        return false;
    for (unsigned int i = 0; i < m_length; i++)
    {
        if (m_szStr[i] != that.m_szStr[i])
            return false;
    }
    return true;
}

String String::operator+(const String& that) const
{
    String temp(m_length + that.m_length - 1);
    unsigned int offset = m_length;
    for (unsigned int i = 0; i < that.m_length; i++)
    {
        temp.m_szStr[offset] = that.m_szStr[i];
    }
    return temp;
}

String::operator const char*() const
{
    return m_szStr;
}

int String::findStr(char* pch) const
{
    unsigned int offset = 0;
    unsigned int strIndex = -1;
    for (unsigned int i = 0; m_szStr[i] != NULL && pch[offset] != NULL; i++)
    {
        if (m_szStr[i] == pch[offset])
        {
            if (strIndex == -1)
                strIndex = i;
            offset++;
        }
        else
        {
            strIndex = -1;
            offset = 0;
        }
    }
    return strIndex;
}

int String::getLen() const
{
    unsigned int len = 0;
    for (unsigned int i = 0; m_szStr[i] != NULL; i++)
    {
        len++;
    }
    return len;
}

void String::copyStr(const char* pch)
{
    if (!m_szStr)
        delete[] m_szStr;
    unsigned int pchLen = 0;
    for (unsigned int i = 0; pch[i] != NULL; i++)
    {
        pchLen++;
    }
    m_length = pchLen;
    m_szStr = new char[m_length];
    for (unsigned int i = 0; i < m_length; i++)
    {
        m_szStr[i] = pch[i];
    }
}

Code file:

#include "stdafx.h"
#include <iostream>
#include "String.cpp"

using namespace std;


int _tmain(int argc, _TCHAR* argv[])s
{
    String s1("Hi!");
    String s2(5);
    s2 = "Hello, Hi!";
    const char* pch = static_cast<const char*>(s2);
    cout << pch << endl;
    return 0;
}

errors:

Error   1   error LNK2005: "public: __thiscall String::String(class String const &)" (??0String@@QAE@ABV0@@Z) already defined in assignment4.obj    C:\Users\****\Desktop\C++ Programming\assignment4\assignment4\String.obj    assignment4
Error   2   error LNK2005: "public: __thiscall String::String(unsigned int)" (??0String@@QAE@I@Z) already defined in assignment4.obj    C:\Users\****\Desktop\C++ Programming\assignment4\assignment4\String.obj    assignment4
Error   3   error LNK2005: "public: __thiscall String::String(char const *)" (??0String@@QAE@PBD@Z) already defined in assignment4.obj  C:\Users\****\Desktop\C++ Programming\assignment4\assignment4\String.obj    assignment4
Error   4   error LNK2005: "public: __thiscall String::~String(void)" (??1String@@QAE@XZ) already defined in assignment4.obj    C:\Users\****\Desktop\C++ Programming\assignment4\assignment4\String.obj    assignment4
Error   5   error LNK2005: "public: class String & __thiscall String::operator=(class String const &)" (??4String@@QAEAAV0@ABV0@@Z) already defined in assignment4.obj  C:\Users\****\Desktop\C++ Programming\assignment4\assignment4\String.obj    assignment4
Error   6   error LNK2005: "public: bool __thiscall String::operator==(class String const &)const " (??8String@@QBE_NABV0@@Z) already defined in assignment4.obj    C:\Users\****\Desktop\C++ Programming\assignment4\assignment4\String.obj    assignment4
Error   7   error LNK2005: "public: __thiscall String::operator char const *(void)const " (??BString@@QBEPBDXZ) already defined in assignment4.obj  C:\Users\****\Desktop\C++ Programming\assignment4\assignment4\String.obj    assignment4
Error   8   error LNK2005: "public: class String __thiscall String::operator+(class String const &)const " (??HString@@QBE?AV0@ABV0@@Z) already defined in assignment4.obj  C:\Users\****\Desktop\C++ Programming\assignment4\assignment4\String.obj    assignment4
Error   9   error LNK2005: "public: void __thiscall String::copyStr(char const *)" (?copyStr@String@@QAEXPBD@Z) already defined in assignment4.obj  C:\Users\****\Desktop\C++ Programming\assignment4\assignment4\String.obj    assignment4
Error   10  error LNK2005: "public: int __thiscall String::findStr(char *)const " (?findStr@String@@QBEHPAD@Z) already defined in assignment4.obj   C:\Users\****\Desktop\C++ Programming\assignment4\assignment4\String.obj    assignment4
Error   11  error LNK2005: "public: int __thiscall String::getLen(void)const " (?getLen@String@@QBEHXZ) already defined in assignment4.obj  C:\Users\****\Desktop\C++ Programming\assignment4\assignment4\String.obj    assignment4
Error   12  error LNK1169: one or more multiply defined symbols found   C:\Users\****\Desktop\C++ Programming\assignment4\Debug\assignment4.exe 1   1   assignment4
πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
Tugal.44
  • 153
  • 4
  • 13
  • Did you link your `String.cpp` file to the executable? – πάντα ῥεῖ Sep 26 '14 at 17:36
  • Possible duplicate of: [What is an undefined reference/unresolved external symbol error and how do I fix it?](http://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external-symbol-error-and-how-do-i-fix) – πάντα ῥεῖ Sep 26 '14 at 17:37
  • @πάνταῥεῖ Their explanation are really tough to understand for a beginner like me – Tugal.44 Sep 26 '14 at 17:47
  • But boil down you've been missing to _link_ your `String.cpp` translation unit, instead you included it. See [here](http://stackoverflow.com/questions/22999116/c-multiple-definition-of-main/22999144#22999144) also. – πάντα ῥεῖ Sep 26 '14 at 17:48
  • @πάνταῥεῖ the problem is the opposite - it's being linked *and* included. – Mark Ransom Sep 26 '14 at 17:53
  • @MarkRansom Arguable if this situation really could be thought of being _opposite_, at least there's an _and_ operation within. But well, you're right. – πάντα ῥεῖ Sep 26 '14 at 17:55
  • @MarkRansom Could you help with the first question ? – Tugal.44 Sep 27 '14 at 01:11
  • Yes, the auto-generated copy constructor will do a member-wise copy, which in the case of simple things like `int` is the proper implementation. And `*this` is correct too. – Mark Ransom Sep 27 '14 at 01:53
  • @MarkRansom If one of the member was a pointer / holding a pointer relying on the default copy-constructor is bad ? will it work ? – Tugal.44 Sep 27 '14 at 02:09
  • When you copy a pointer you blur the ownership of the pointer - which object should delete it? `std::shared_ptr` would be OK though. – Mark Ransom Sep 27 '14 at 02:17

1 Answers1

2

In your main code file, write:

#include "String.h"   // with .cpp you redefine everything !! 

Currently you include String.cpp. So in your main file you will redefine everything you have already defined in String.cpp. It will compile, but the linker will be confused because he will find a definition for your String member functions in String.obj as well as in main.obj ("one definition rule").

And you already answerd yourself your copy constructor question

Christophe
  • 68,716
  • 7
  • 72
  • 138
  • but why do I need to include String.h and not .cpp ? the .cpp include the definition and the .cpp is the implementation so if I were to include just the .h file I'll only include the definition, no ? – Tugal.44 Sep 26 '14 at 17:47
  • 1
    @Tugal.44 there's a process called "linking" that combines the compiled output of different .cpp files together. When you `#include` it also, you get two copies. – Mark Ransom Sep 26 '14 at 17:54
  • Because String.h contains the declarations. These are sufficient for the compiler to generate code, that the linker will then link with the result of the sring.cpp compilation. – Christophe Sep 26 '14 at 17:55
  • If I were using gcc would it be the same ? Say I would write g++ code.cpp -o code this will only link the code object file without the String so I would have to include the String.cpp ? – Tugal.44 Sep 26 '14 at 18:02
  • You could certainly include your String.cpp, and compile only your code.cpp. But this approach is very limited in practice. The problem is that you'll have more and more cpp and you won't be able to find out when to include an not the cpp, etc... If you intend to write real software, you'll have to get used to multiple compilation units. WIth g++ you'd write g++ code.cpp string.cpp -o code – Christophe Sep 26 '14 at 19:16
  • @Christophe but if I would just compile code.cpp I would have to include string.cpp correct ? and if I were to compile both string.cpp and code.cpp I would have to include only the defenition file which is the string.h correct ? If that's the case then I guess I didn't know Microsoft Visual studio will compile all cpp files in the folder, btw can someone answer my first question ? – Tugal.44 Sep 26 '14 at 19:57