Hallo,
ich dachte, das Thema Konstruktoren verstanden zu haben, aber dem ist
wohl nicht so...
Gegeben ist folgender Quellcode, wobei die Konstruktoren in der Form
auch ohne explizites Hinschreiben vom Compiler automatisch hinzugefügt
würden:
1 | #include<string>
|
2 | #include<memory>
|
3 | #include <iostream>
|
4 |
|
5 | using namespace std;
|
6 |
|
7 | class SimplerName {
|
8 |
|
9 | public:
|
10 | void setName(const std::string& s) {
|
11 | m_name = s;
|
12 | }
|
13 |
|
14 | std::string getName() const{
|
15 | return m_name;
|
16 | }
|
17 | // Standardkonstruktor
|
18 | SimplerName()
|
19 | : m_name() {}
|
20 |
|
21 | // Kopierkonstruktor
|
22 | SimplerName(const SimplerName& n)
|
23 | : m_name{ n.m_name } { }
|
24 |
|
25 | // Verschiebekonstruktor
|
26 | SimplerName(SimplerName&& n)
|
27 | : m_name{ static_cast<std::string&&>(n.m_name) } {}
|
28 | // es ginge auch : m_name{ std::move(n.m_name) } { }
|
29 |
|
30 | // Kopier-Zuweisungsoperator
|
31 | SimplerName& operator=(const SimplerName& n) {
|
32 | m_name = n.m_name;
|
33 | return *this;
|
34 | }
|
35 | // Verschiebe-Zuweisungsoperator
|
36 | SimplerName& operator=(SimplerName&& n) {
|
37 | m_name = static_cast<std::string&&>(n.m_name);
|
38 | return *this;
|
39 | }
|
40 | // Destruktor
|
41 | ~SimplerName() {}
|
42 |
|
43 | private:
|
44 | std::string m_name;
|
45 | };
|
46 |
|
47 |
|
48 |
|
49 | int main() {
|
50 | SimplerName n1; // Standardkonstruktor
|
51 | n1.setName("Peter");
|
52 | SimplerName n2(n1); // Kopierkonstruktor
|
53 | SimplerName n3;
|
54 | n3 = n2; // Kopier-Zuweisungsoperator
|
55 | cout << n1.getName() << endl;
|
56 | cout << n2.getName() << endl;
|
57 | cout << n3.getName() << endl;
|
58 | cout << "---------" << endl;
|
59 |
|
60 | n2 = move(SimplerName()); // Verschiebe-Zuweisungsoperator
|
61 | SimplerName n4(move(SimplerName())); // Move-Konstruktor
|
62 | cout << n2.getName() << endl;
|
63 | cout << n4.getName() << endl;
|
64 | }
|
Das ganze läuft erstmal durch. 'n2' und 'n4' besitzen keinen Namen bzw.
das Attribut 'm_name' ist leer, da in den zugehörigen Anweisungen in den
letzten Zeilen nichts angegeben wird.
Warum aber funktionieren die folgenden Zeilen nicht?
Ich dachte, das wäre genau der Trick an der Sache, daß temporäre
namenlose Objekte wie "Schmidt" übergeben werden können?
1 | n2 = move(SimplerName{ "Schmidt" }); // error: no matching function for call to 'SimplerName::SimplerName(<brace-enclosed initializer list>)'|
|
2 | n2 = move(SimplerName( "Schmidt" )); // error: no matching function for call to 'SimplerName::SimplerName(const char [8])'|
|
3 |
|
4 | n2 = SimplerName{ "Schmidt" }; // error: no matching function for call to 'SimplerName::SimplerName(<brace-enclosed initializer list>)'|
|
5 | n2 = SimplerName( "Schmidt" ); // error: no matching function for call to 'SimplerName::SimplerName(const char [8])'|//
|
6 |
|
7 | SimplerName n5(move(SimplerName{ "Meier" }));
|
8 | SimplerName n5(move(SimplerName( "Meier" )));
|
9 |
|
10 | SimplerName n5(SimplerName{ "Meier" });
|
11 | SimplerName n5(SimplerName( "Meier" ));
|
12 |
|
13 | SimplerName n5{SimplerName{ "Meier" }};
|
In einem Beispiel vorher hat der Autor eine Klasse 'Name' implementiert,
da funktioniert das alles. Allerdings wird hier auf das 'move'
verzichtet, der Aufruf lautet einfach:
1 | Name n7{ Name{ "Muller" } };
|
Wo ist hier der Unterschied bzw. was muß ich in 'SimplerName' ändern, um
einen Namen übergeben zu können?
In der Klasse 'Name' sind die Konstruktoren selbst geschrieben. Ändere
ich den Verschiebekonstruktor in 'SimplerName' entsprechend ab,
funktioniert das jedoch nicht:
1 | SimplerName(SimplerName&& n) {
|
2 | m_name = n.m_name;
|
3 | n.m_name = nullptr;
|
4 | }
|
Wieso nicht?