String type allowed in copy constructor?

Jul 30, 2018 at 8:51pm
I am using an example from Sams Teach Yourself C++ In One Hour a day. I pretty much understand concepts relating to the copy constructor. A couple of things that I can use a hand on are;
Why can I put just a string in the
 
UseMyString("string");

an instance of a MyString object is called sayHello is legal
 
UseMyString(sayHello);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#include <iostream>
#include <string.h>
using namespace std;

class MyString
{
private:
	char* buffer;

public:

	MyString(const char* initString) // constructor
	{
		buffer = NULL;
		cout << "Default constructor: creating new MyString" << endl;
		if (initString != NULL)
		{
			buffer = new char[strlen(initString) + 1];
			strcpy(buffer, initString);

			cout << "buffer points to: 0x" << hex;
			cout << (unsigned int*)buffer << endl;
		}
	}

	MyString(const MyString& copySource) // Copy constructor
	{
		buffer = NULL;
		cout << "Copy constructor: copying from MyString" << endl;
		if (copySource.buffer != NULL)
		{
			// allocate own buffer 
			buffer = new char[strlen(copySource.buffer) + 1];

			// deep copy from the source into local buffer
			strcpy(buffer, copySource.buffer);

			cout << "buffer points to: 0x" << hex;
			cout << (unsigned int*)buffer << endl;
		}
	}

	// Destructor
	~MyString()
	{
		cout << "Invoking destructor, clearing up" << endl;
		delete[] buffer;
	}

	int GetLength()
	{
		return strlen(buffer);
	}

	const char* GetString()
	{
		return buffer;
	}
};

void UseMyString(MyString str)
{
	cout << "String buffer in MyString is " << str.GetLength();
	cout << " characters long" << endl;

	cout << "buffer contains: " << str.GetString() << endl;
	return;
}

int main()
{
	MyString sayHello("Hello from String Class");
	UseMyString(sayHello);
        //UseMyString("string"); this is not required type but it still compiles

	return 0;
}
Last edited on Jul 30, 2018 at 8:57pm
Jul 30, 2018 at 8:55pm
Because C++ will implicitly convert the const char* into a MyString.

To prevent this confusion, mark your MyString constructor as explicit.
explicit MyString(const char* initString) { /* ... */ }

Further reading:
https://softwareengineering.stackexchange.com/questions/190716/is-relying-on-implicit-argument-conversion-considered-dangerous
https://blogs.msdn.microsoft.com/oldnewthing/20060524-12/?p=31083
Last edited on Jul 30, 2018 at 8:58pm
Jul 30, 2018 at 8:56pm
Unless you make a constructor "explicit" it acts as a conversion function. So UseMyString("hello") first calls the MyString ctor that takes a string literal, creates a MyString object, and passes it to UseMyString. If you put the keyword "explicit" in front of the first MyString ctor then it won't be used implicitly like that.
Jul 30, 2018 at 9:04pm
OK @Ganado, @tpb I see. I am learning about the keyword explicit. This helps so much Thanks
Topic archived. No new replies allowed.