Inherited Code Discussions | C++ | HackerRank

Inherited Code

  • + 1 comment

    following makes use of sstream. No need to create object on heap:

    const char* what() const throw() {
        stringstream ss;
        string error;
    
        ss << n; //Integer passed to exception object
    
        error = ss.str();
    
        return(ss.c_str());  
    }
    

    This makes use of "c_str()" which converts your std::string to const char* (which is what c syntax for representing strings)

    • + 3 comments

      That's an error! You returning a pointer to an object (int this case error that is destroyed after function call).

      That's really dangerous! You need to store the string inside the class so error string must be inside the class.

      class BadLengthException {
      public:
      	BadLengthException(int n) {
          	stringstream ss;
          	ss << n;
          	m_error = ss.str();
          }
          
      	const char* what() const throw() {
          	return m_error.c_str();
      	}
          
      private:
          string m_error;
      };
      
      • + 0 comments

        Right, thanks for pointing out

        Actually found this out after I posted and the first exception started returning garbage values :/

      • + 1 comment

        why did you define stringstream variable inside the constructor? and Why cant I define ss as a class variable, inside the private block ?

        class BadLengthException: public exception{
            stringstream ss;
            string error;
        public:
            BadLengthException(int n)
            {
                ss<<n;
                error = ss.str();
            }
            virtual const char* what() const throw()
            {
                return error.c_str();
            }
        };
        
        • + 5 comments

          Because in here

          catch (BadLengthException e)
          

          BadLengthException's copy ctor is being used.

          Stringstream's copy ctor is deleted, so if you define it as class variable, then BadLengthException copy ctor is implicitly deleted as well.

          • + 3 comments

            So I had this at first (and tried stringstream as a class variable) and couldn't figure out why it wasn't working. It either printed out weird characters or nothing (or spaces?).

            class BadLengthException: public exception
            {
                int error;
                
                public:
                    BadLengthException (int n) : error(n) {}
                    
                    virtual const char* what() const throw()
                    {
                        stringstream num;
                        num << error;
                        return num.str().c_str();         
                    }
            };
            

            Then, I tried testing with cout the num-to-cstring conversion and it prints out the correct value. This actually passed the testcases lol.

            virtual const char* what() const throw()
                    {
                        stringstream num;
                        num << error;
                        cout << num.str().c_str();
                        return "";        
                    }
            

            This is when I checked the discussion and found elvis_dukaj's solution using stringstream inside the constructor and making the string object a class variable.

            So, I'm wondering why the cout works but when using return, it doesn't?

            Also, I read Pan_Zloto's explanation but still confused. So I guess I'd like a better explanation. Why can't you use a stringstream class variable but a string class variable works?

            • + 0 comments

              because in case of stringsteam on the stack of the function it goes out of scope at the end of a function , so c_str is no longer valid .

            • + 0 comments

              Why is there two const?

          • + 1 comment

            I didn't really understood this. I don't know much about how the copy constructor works, and when it is deleted. So, looking for some more explanation! Thanks for the help though!

            • + 0 comments

              the copy constructor defines how to copy objects of the class "properly". If undefined than it just duplicates the members of the class (this is an issue if they are pointers to other objects/variables you want copying).

              If the copy constructor is marked as deleted, then the object cannot be copied as the compiler doesn't know how its supposed to copy it.

          • + 0 comments

            Would be great if you could explain more, as per P0kerZ request. :)

          • + 0 comments

            In main function, in line 35th, exception is caught by value, not by reference:

            } catch (BadLengthException e) {
            

            what it means is that in this line, 'e' is a copy of an exception thrown from checkUsername(). It is somehow analogical to passing arguments to functions - you can do it by value, and then copy constructor is called (in other words, a copy of originaly passed variable is created inside of a function), or you can do it by reference, and then original variable is used inside of a function. When you throw an exception you can caught by value - so you're creating a copy of originaly thrown exception, or by reference - and use original exception.

            When you call copy ctor of a class, copy ctors of all of its member variables are called as well, so in this example, if a std::stringstream was part of a class, not a local variable of a constructor, a copy ctor of it would have to be called. But because it is marked as deleted, it can't be called, and that is why code can't be compiled.

            You can read about deleted function here: http://en.cppreference.com/w/cpp/language/function#Deleted_functions

            Is it more clear now?

          • + 0 comments

            BTW, look at this solution: https://www.hackerrank.com/challenges/inherited-code/forum/comments/399496

      • + 0 comments

        Thank you for your explain. I spent very time to understand what is that's problem. the point you said was really perfect and professional.