具有继承实现的 C++ 5 法则

C++ Rule of 5 with inheritance implementation

提问人:Andrea 提问时间:9/6/2021 最后编辑:Zoe is on strikeAndrea 更新时间:9/6/2021 访问量:250

问:

按照在线教程中关于 5 规则的示例,我编写了以下课程:

#include <iostream>
#include <cstring>
#include <utility>
class A2
{
    char* _buff;
public:
    A2(const char *text = "test") {
        std::cout << "New A2\n";
        _buff = new char[256];
        size_t length = strnlen(text, 255) + 1;
        strncpy(_buff, text, length);
    }
    
    virtual ~A2() {
        std::cout << "Delete A2\n";
        delete[] _buff;  // deallocate
    }
    
    A2(const A2& other) : A2(other._buff) {
        std::cout << "Copy constructor A2\n";
    }
    
    A2(A2&& other) noexcept : _buff(std::exchange(other._buff, nullptr)) {
        std::cout << "Move constructor A2\n";
    }
    
    A2& operator=(const A2& other) {
        std::cout << "Copy assignment A2\n";
        return *this = A2(other);
    }
    
    A2& operator=(A2&& other) noexcept {
        std::cout << "Move assignment A2\n";
        std::swap(_buff, other._buff);
        return *this;
    }
};

做一些测试,它实际上似乎对我有用(它是通过示例中的一些自定义项复制的)。

因此,我尝试创建一个继承自 A2 的类(在这种情况下,作为构造函数参数的文本也传递给父级,但在它们的内部管理中它们保持独立):

class B2 final : public A2
{
    char* _buff2;
public:
    B2(const char* text) : A2(text) {
        _buff2 = new char[256];
        size_t length = strnlen(text, 255) + 1;
        strncpy(_buff2, text, length);
        std::cout << "new B2\n";
    }

    ~B2() {
        std::cout << "delete B2\n";
        delete[] _buff2;  // deallocate
    }
    
    B2(const B2& other) : A2(other) {
        _buff2 = new char[256];
        size_t length = strnlen(other._buff2, 255) + 1;
        strncpy(_buff2, other._buff2, length);
        std::cout << "copy constructor B2\n";
    }
    
    B2(B2&& other) noexcept  : A2(static_cast<A2&&>(other)), _buff2(std::exchange(other._buff2, nullptr))
    {
        std::cout << "move constructor B2\n";
    }
    
    B2& operator=(const B2& other) {
        std::cout << "operator = in B2\n";
        A2::operator= (other);
        size_t length = strnlen(other._buff2, 255) + 1;
        strncpy(_buff2, other._buff2, length);
        return *this;
    }
    
    B2& operator=(B2&& other) noexcept {
        std::cout << "move assignment B2\n";
        A2::operator=(static_cast<A2&&>(other));
        std::swap(_buff2, other._buff2);
        return *this;
    }
};

它似乎工作正常(我也在这里做了一些测试,并检查调试器是否一切正常)。

但我的疑问是:为 B2 类写的是正确的吗?我不太相信直接使用运算符 ( 并将参数传递给父级。A2::operator = (other)A2::operator = (static_cast <A2&&> (other)))

有没有办法更清晰、更正确地编写相同的代码?

C++ 继承 五法则

评论

1赞 Ted Lyngmo 9/6/2021
A2(static_cast<A2&&>(other))最好写成 - 另外,为什么不分配同样多的内存呢? 和A2(std::move(other))A2(const char* text, size_t len) : len_(len), buff_(new char[len_ + 1]) { std::copy_n(text, len_ + 1, _buff); }A2(const char* text = "test") : A2(text, std::strlen(text)) {}
1赞 t.niese 9/6/2021
Is there any way to write the same code more clearly and correctly?使用 instead of 会使很多事情变得更容易。当你使用它时,它表明它是一个字符串,所以使用可能是更好的选择?(当然,如果你想学习这个,这并不能回答如何正确地执行五法则,但一般来说,你想把容易出错的工作转移到编译器和std上)std::vector<char>char *strncpystd::string
1赞 Phil1970 9/7/2021
如果可能,请仅使用可为成员复制或移动的类型(例如要复制或移动的类)来使用规则 0。代码越简单,越容易理解,越不容易出错。std::string
2赞 n. m. could be an AI 9/7/2021
多态层次结构需要禁用复制和移动。由于对象切片,您永远不想按值传递它们或分配它们。
2赞 n. m. could be an AI 9/7/2021
@Andrea 这不是一个绝对的要求,只是一个经验法则。

答: 暂无答案