0

I have a problem when I derive a String class from std::string and I test it.

Here is the String class:

namespace Types
{

class String : public std::string
{
public:
    String();

    /*!
     * @fn String(const String &other);
     * @brief Copy contructor
     * @param other
     */
    String(const String &other)
        : std::string(other) {}
    String(const char* format_string, ...);

    virtual ~String();
};

} /* namespace Types */

And here is the test class :

class String_test : public CppUnit::TestFixture
{
    CPPUNIT_TEST_SUITE(String_test);
    CPPUNIT_TEST(testCopyConstructor);
    CPPUNIT_TEST_SUITE_END();

public:
    void setUp(void)
    {
        mTestObj = new Types::String();
    }
    void tearDown(void)
    {
        delete mTestObj;
    }

protected:
    void testCopyConstructor(void)
    {
        *mTestObj = "toto";
        std::cout << *mTestObj << std::endl;
        Types::String new_string((const Types::String&)mTestObj);
        CPPUNIT_ASSERT(true == true);
    }
private:
    Types::String *mTestObj;
};

The compilation is ok but when the program is running I have this error:

##Failure Location unknown## : Error
Test name: String_test::testCopyConstructor
uncaught exception of type std::exception (or derived).
- basic_string::_M_construct null not valid

I have searched the documentation about copy constructor and derived class, it seems that is ok in code. I don't understand what's the problem.

Anyone have an idea ?

Thanks

3
  • 3
    stackoverflow.com/questions/6006860/… Deriving from string is bad practice Commented Mar 25, 2020 at 15:54
  • You probably meant to use *mTestObj instead of (const Types::String&)mTestObj. Avoid C style casts, they let you cast all sorts of things to other things they shouldn't be casted to. If adding one fixes a compiler error, most of the time it's just hiding it from you without actually fixing anything. Commented Mar 25, 2020 at 15:54
  • 1
    pubplicly inheriting from standard types is a bad idea in general. Privately inheriting is fine, but then you might as well use composition over inheritance. Commented Mar 25, 2020 at 16:07

1 Answer 1

1

mTestObj is a pointer, so

(const Types::String&)mTestObj

cannot be interpreted as static_cast<const Types::String&>(mTestObj), because there is no constructor of Types::String that takes a Types::String*.

So it will be interpreted as

 reinterpret_cast<const Types::String&>(mTestObj)

which has the same meaning as

 *reinterpret_cast<const Types::String*>(&mTestObj)

Because there is no Types::String object at the address of mTestObj (the pointer), accessing the result of this cast as if there was causes undefined behavior. This happens in the std::string copy constructor. Alternatively the result of the cast might already be unspecified if there is alignment mismatch for Types::String.

Do not use C-style casts, as you can see they are very dangerous.

You obtain a reference from a pointer using * and you can get a const reference by calling std::as_const on that:

Types::String new_string(std::as_const(*mTestObj));

although I am not sure why you would need const in the first place, so probably really you want just

Types::String new_string(*mTestObj);
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.