如何调用超类的复制构造函数/操作符=?

问题描述 投票:0回答:1

我有一个带有堆成员“a”的 A 类:

class A {
protected:
    char *name;

public:
    // Constructor
    A() {
        name = new char[10];
        strcpy(name, "Undefined");
    }

    // Assignment Operator
    virtual A &operator=(const A &rhs) {
        if (this == &rhs) {
            return *this;
        }

        delete [] name;
        name = new char[10];
        strcpy(name, rhs.name);

        return *this;
    }

    // Destructor
    virtual ~A() {
        delete [] name;
    }
};

我有带有附加变量“b”的子类 B:

class B : public A {
    int b;

    // Constructor
    B():A(),b(0){}

    // Assignment Operator
    virtual B& operator=(const B& rhs) {
        if (this == &rhs) {
            return *this;
        }

        delete [] name;
        name = new char[10];
        strcpy(name, rhs.name);

        b = rhs.b;

        return *this;
    }

    // Destructor
    virtual ~B() {
        delete [] name;
    }
};

我的子类 C 带有附加成员“char* name”:

class C : public A {
    int* c;

    // Constructor
    C():A() {
        c = new int[10];
        for(int i = 0 ; i < 10 ; i++) {
            c[i] = 0;
        }
    }

    // Assignment Operator
    virtual C& operator=(const C& rhs) {
        if (this == &rhs) {
            return *this;
        }

        delete [] name;
        name = new char[10];
        strcpy(name, rhs.name);

        delete [] c;
        c = new int[10];
        for (int i = 0 ; i < 10 ; i++) {
            c[i] = rhs.c[i];
        }

        return *this;
    }

    // Destructor
    virtual ~C() {
        delete [] name;
        delete [] c;
    }
};

我想知道这是否是为 B 和 C 实现运算符=和析构函数的正确方法。 有没有办法在B或C中调用A的operator=或析构函数,这样我就不用一遍又一遍地给所有成员写赋值了。

  • A 是带有堆变量的基类
  • B 是从 A 派生的类,带有附加的“int b”
  • C 是从 A 派生的类,带有附加的“char* name”
c++ object oop c++17 superclass
1个回答
0
投票

回答所问的问题,是的,派生类

operator=()
可以调用基类
operator=()
。例如;

    B& operator=(const B& rhs) {
       A::operator=(rhs);
       b = rhs.b;
       return *this;  
    }

(与

C
类似)。

然而,这并不是一个特别好的方法。接下来,我将解决一些您没有询问过的对您的方法的担忧。

  1. 您的

    operator=()
    不一定是虚拟的。

  2. 最好根本不声明或定义

    B::operator=()
    。这样做允许
    B::operator=()
    隐式生成(例如由编译器),并且隐式生成的版本调用基类版本,并按值复制/分配所有成员。自行推出的唯一原因是隐式生成的
    operator=()
    不适合您的派生类。

另外,

if (this == &rhs)
中的
A::operator=()
是不需要做的。相反,它可以定义为

A &operator=(const A &rhs) {
    char *newname = new char [std::strlen(rhs.name)];
    strcpy(newname, rhs.name);
    delete [] name;
    name = newname;
    return *this;
}

除了避免

this == &rhs
测试(如果
A
operator&()
将会产生不同的行为)之外,这种方法也是安全的 - 如果
new
表达式抛出异常,则对象不会改变。

这样做的唯一缺点是,暂时会产生少量额外的内存使用(在

name
被释放并重新分配之前,
rhs.name
newname
name
都会消耗内存)。

使用这种方法,

C::operator=()
将被实现来调用
A::operator=()
并分配/复制/释放
c

此外,

B
C
的析构函数通常不应释放
A
的成员。当
B
C
被破坏时,
A
的构造函数被隐式调用(因此您的方法将导致
A::name
被破坏两次,从而导致未定义的行为。

最后,您可以使用标准容器(

std::string
std::vector<char>
),并完全避免手动内存分配(
new
delete
)。有关更多信息,请参阅“零C++规则”。

© www.soinside.com 2019 - 2024. All rights reserved.