1

I am a newbie in C++. I wrote this code to understand the difference between public, protected and private. The problem is, when I create an object of Hund4, I get this error:

use of deleted function

This error is in the last line.

Can you please help me to solve this problem?

#include <iostream>
#include <iostream>
#include <string>
using namespace std;

class Tier
{
public:
    void wieMachtDasTier()
    {
        cout << "Hello\n";
    }

protected:
    void foo()
    {
        cout << "foo\n";
    }

private:
    void baz()
    {
        cout << "baz\n";
    }
};

class Hund: public Tier
{
private:
    string name;

public:
    Hund(string newname):name(newname){}

    string getname()
    {
        return this->name;
    }

    void test()
    {
        foo();
    }
};

class Hund2: protected Tier
{
public:
    void test()
    {
        foo();
    }
};

class Hund3: private Tier
{
public:
    void test()
    {
        foo();
    }
};

class Hund4 : public Hund
{

};

int main()
{
    Hund ace("ace");
    ace.wieMachtDasTier();
    Tier Haustier;
    ace.test();
    Hund2 ace2;
    ace2.test();
    Hund3 ace3;
    ace3.test();
    Hund4 ace4;
    return 0;
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • When asking questions about build errors, first please make sure that your [mre] really is minimal. Secondly copy-paste (as text) the full and complete build log into the question itself. If you look through it there may even be hints and information that helps you solve the problem yourself. – Some programmer dude May 26 '22 at 23:18
  • Does this answer your question? [error: use of deleted function](https://stackoverflow.com/questions/5966698/error-use-of-deleted-function) – Karl Knechtel May 26 '22 at 23:47

2 Answers2

1

The Hund class that Hund4 derives from has no default constructor, so Hund4 has no default constructor. You can construct a Hund4 from a std::string or a Hund, though:

Hund4 ace4(std::string{"ace4"});
Hund4 ace4(Hund{"ace4"});

using std::literals;
Hund4 ace("Waldi"s);

For some reason, somebody else please explain why a const char * is sufficient for Hund but doesn't work for Hund4.

Or, you have to give Hund4 a constructor:

class Hund4 : public Hund
{
  public:
    Hund4(string newname) : Hund(newname) { }
};

Hund4 ace4("ace4");
Goswin von Brederlow
  • 11,875
  • 2
  • 24
  • 42
  • Hi Goswin! Thank you for your answer! The problem is that i tried it but this time i get another error which is 'no matching function for call to Hund4::(const char[5])' For the other classes i didn't define the objects that way. For example i wrote only Hund3 ace3; and it worked. I am kinda confused why it didnt work for Hund4. – The_Beginner May 26 '22 at 23:22
  • @The_Beginner this variant is closer to correct than what you currently have. In another few hours you can, and should if you haven't figured it out by then, ask a question about it. – user4581301 May 26 '22 at 23:24
  • @goswin von Brederlow i created a constructor now for the class Hund4 as you mentioned and it worked. My question is: Why could i create an object of the other classes without the constructor (for example Hund2 and Hund3) but for the class Hund4 it was necessary to add a constructor. So is it because the class Hund4 inherited the class Hund, which has a constructor and the other classes (Hund2 and Hund3) inherited the class Tier, which doesent have a constructor? – The_Beginner May 26 '22 at 23:35
  • 1
    @The_Beginner `Hund2` and `Hund3` both have a compiler-generated default constructor, because they derive from `Tier` which has a compiler-generated default constructor. `Hund` has a user-defined constructor, so it does not have a compiler-generated default constructor, and so neither does `Hund4`, either. If you want `Hund4` to be default-constructable, it needs its own user-defined default constructor that calls `Hund`'s non-default constructor, eg: `Hund4() : Hund("") { }` or `Hund4(string newname = "") : Hund(newname) { }`. – Remy Lebeau May 26 '22 at 23:43
  • @Remy Lebeau Thank you very much that explains a lot! But i still have another question: if i want Hund4 to be default-constructable then i have to remove the user-defined constructor from Hund? how can make its own user-defined default constructor that calls Hund' s non-default constructor? – The_Beginner May 26 '22 at 23:47
  • @The_Beginner No, you can just give the Hund a default name like in: `Hund4() : Hund("") { }` or `Hund4(string newname = "") : Hund(newname) { }`. Or add a default name in `Hund(string newname = "") ...`. – Goswin von Brederlow May 26 '22 at 23:54
  • @Goswin von Brederlow Thanks a lot! – The_Beginner May 26 '22 at 23:59
  • Using `std::string` literals works too. – Goswin von Brederlow May 27 '22 at 00:02
1

Tier has no user-declared constructors, and std::string is default-constructable, so Tier has a compiler-generated default constructor.

Hund2 and Hund3 derive from Tier, have no user-declared constructors, and do not have any non-default-constructable data members, so they have compiler-generated default constructors as well.

Hund, on the other hand, has a user-declared constructor, so it does not have a compiler-generated default constructor.

Hund4 has no user-declared constructors, but Hund is not default-constructable, so Hund4 does not have a compiler-generated default constructor.

So, if you want Hund4 to be default-constructable, you need to either:

  • make Hund default-constructable, eg:

    class Hund: public Tier
    {
    private:
        string name;
    
    public:
        Hund() {}
        Hund(string newname) : name(newname) {}
    
        // or:
        // Hund(string newname = "") : name(newname) {}
    
        ...
    };
    
  • give Hund4 its own user-declared default constructor, which calls Hund's non-default constructor, eg:

    class Hund4 : public Hund
    {
    public:
        Hund4() : Hund("") { }
    
        // or:
        // Hund4(string newname = "") : Hund(newname) { }
    };
    
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770