Is this a good reason for non-polymorphic inheritance?

std::string(like most - if not all - standard classes) does not have virtual methods, so creating an inherited class with virtual methods will lead to UB (because of, most likely, the destructor). (correct me if I am wrong).

I thought that inheritance without polymorphism is still good, until I read online on this subject.

For example, in this answer: Why shouldn't std string class be derived from C ++? some arguments are against this practice. The main reason, apparently, is the problem of slicing, which will hinder the added functionality when the derived object is passed to the function instead of the parameter std::string, which makes non-polymorphism illogical. The idiomatic way of C ++ is to create free functions if you want to extend functionality string. And I agree with all this, especially since I am a supporter of free functions instead of monolithic classes.


Considering that I believe that I have found a situation that, in my opinion, actually guarantees non-polymorphic inheritance from std::string. First, I will show what problem I am trying to solve, then I will show why I believe that inheritance from std::stringis the best solution here.

When porting the function used for debugging from C to C ++, I realized that it is impossible to create formatted strings in C ++ (without using string functions like C, for example sprintf). I.e:.

C version: void someKindOfError(const char *format, ...);
it will look like this:

someKindOfError("invalid argument %d, size = %d", i, size);

C ++ version: void someKindOfError(const std::string &message);
to invoke this effect, it will be similar:

std::stringstream ss;
ss << "invalid argument " << i << ", size = " << size;
someKindOfError(ss.str());

this cannot be a single liner because the operator <<returns ostream. Therefore, this requires two additional lines and an additional variable.

, , - StreamString, std::string ( BasicStreamString, basic_string<>, ), <<, stringstream string.

, :

someKindOfError(StreamString() << "invalid argument " << i << ", size = " << size);

, const std::string &

. , , ad-hoc , stringstream. , a stringstream, string , string.


, ++:

  • , string , string, .
  • () operator <<, string ( ).

, , . - :

template <class... Args>
std::string createString(Args... args);

:

someKindOfError(createString("invalid argument ", i , ", size = " , size));

stringstream . , , . << .


:

  • ( ), ++, ?
  • , ? createString ? ?
+4
2

std::string. , StringBuilder, std::stringstream . < std::string.

- ():

class StringBuilder
{
    std::ostringstream oss;

public:
    operator std::string() const
    {
        return oss.str();
    }

    template <class T>
    friend StringBuilder& operator <<(StringBuilder& sb, const T& t)
    {
        sb.oss << t;
        return *this;
    }
};
+4

StreamString , , , , . , , .

  • , ​​ Boost.Format, , . , , , ..

  • someKindOfError , C, ++. C .

  • StringStream a to_string, std::string. StringStream . (, , - , , , StringStream).

    , . , , StringStream std::string. .

  • StringStream :

someKindOfError(static_cast<std::stringstream &>(
    std::stringstream{} << "invalid argument " << i << ", size = " << size).str());

... , , , , . , , , , , .

+1

Source: https://habr.com/ru/post/1541899/


All Articles