Hello! I am a pythonist, but out of decency I decided to care with ++. Task: there is a class Foo with a private constructor. There is a function foo_says which uses the public method of the class Foo . We need to write a function get_foo , thanks to which it will be compiled:

 foo_says(get_foo("Hello!")); 

Code:

 #include <iostream> #include <stdio.h> #include <cstddef> // size_t #include <cstring> // strlen, strcpy using namespace std; struct Foo { void say() const { std::cout << "Foo says: " << msg << "\n"; } protected: Foo(const char *msg) : msg(msg) { } private: const char *msg; }; struct Fo : Foo { Fo(const char* msg) : Foo(msg) { } }; void foo_says(const Foo &foo) { foo.say(); } const Foo& get_foo(const char *msg) { const Fo F(msg); const Foo& f = F; return f;; } int main() { foo_says(get_foo("Hello!")); return 0; } 

Solution and problem: Since the task is from the section "Class Inheritance", I inherited Fo , which will create an object, and then it can be brought (truncated) to the Foo object. But instead of the Hello line, I get . . I suspect that after exiting some function, the pointer to Hello is deleted, because "Foo says" is displayed correctly. Then where is this happening - I can not understand?

  • The training task is contrary to the rules of glass flow. - Arkady

2 answers 2

Let's start with what you have set

class Foo with private constructor

and you make protected . To reach a private constructor, only a friend is needed. So if inheritance is badly needed, then declare the heir a friend:

 class Fo; class Foo { Foo(const char *msg) : msg(msg) { } public: void say() const { std::cout << "Foo says: " << msg << "\n"; } private: string msg; friend class Fo; }; class Fo : public Foo { public: Fo(const char* msg) : Foo(msg) { } }; 

As for the get_foo function, you can get out of it ( @Majestio told you what the trouble is in it), or by returning a pointer

 const Foo* get_foo(const char *msg) { return new Fo(msg); } 

or link to static object:

 const Foo& get_foo(const char *msg) { static Fo(msg); return Fo; } 

The minus of the second solution is obvious - the object is one, and you cannot create the second one. The minus of the first is in the return of the pointer, which must be stored and do not forget to delete later.

The main project minus is that you want to return a link to Foo , which is actually a link to Fo .

Personally, I would solve the problem without inheritance, because there is not a word about it, and to access the private constructor, you still need a friendship:

 class Foo { Foo(const char *msg) : msg(msg) { } public: void say() const { std::cout << "Foo says: " << msg << "\n"; } private: string msg; friend Foo get_foo(const char *msg); }; void foo_says(const Foo &foo) { foo.say(); } Foo get_foo(const char *msg) { return Foo(msg); } int main() { foo_says(get_foo("Hello!")); } 

By the way, pay attention to the fact that I made a member of the msg string - now it doesn’t matter, but all of a sudden you still want to use this class, and you will not pass to the constructor in the constructor ...

     const Foo& get_foo(const char *msg) { const Fo F(msg); const Foo& f = F; return f;; } 

    This is where you return the link to the local visibility object. This leads to a state of "undefined behavior" (undefined behavior). Until it is decided, there is no point in further digging.

    • I also tried to transfer the object itself so that it could be copied, but in that case, I do not receive IN GENERAL any output - Vladislav Ladenkov
    • + I know for sure that the type of this function must be const Foo& => exactly the link should be returned. What should you do then? - Vladislav Ladenkov
    • one
      Refer to a known entity. For example, on the class object field. While the object is there, there is its field. No matter what is there, it is important that it is - and you can refer to it. The second option is to create an object on the heap. - Majestio
    • Obviously, the authors of the assignment wanted to return * this - Arkady