继承与动态内存分配

继承与动态内存分配

在基类或派生类中含有指针时,要考虑内存分配情况(new与delete),还要考虑在进行对象间赋值时指针隐藏的问题(使用默认复制构造函数在析构时会造成原对象中的指针指向的内存空间被释放,为浅复制

因此需要:
1. 重载运算符’=‘、’<<‘,实现深度复制
2. 在构造函数中使用new进行动态内存分配,在析构函数中使用delete进行内存释放;
3. 将析构函数声明为虚函数

在以下代码中还有一个小技巧来简化代码,即代码重用,在后续代码中使用已定义过的代码,例如:在C的构造函数中使用已经定义过的A的构造函数,这样就可以只对C类新增的数据部分进行初始化。

#include <iostream>
#include <string>
#include <cstring>
using namespace std;

class A {
private: 
    char *label;  //使用指针,需要动态分配内存
    int a;
public: 
    A( const char* l = "null", int t = 0 );
    A( const A& t );
    virtual ~A();
    A& operator=( const A& t );
    friend ostream& operator<<( ostream& out, const A& t );
};

class B : public A {
private: 
    enum{ COL_LEN = 40 };
    char color[COL_LEN]; //使用数组,不需要重新分配内存
public: 
    B( const char *c = "blank", const char *l = "null", int t = 0 );
    B( const char *c, const A& t );
    friend ostream& operator<<( ostream& out, const B& t );
};

class C : public A {
private: 
    char *style;
public: 
    C( const char *s = "none", const char * l = "null", int t = 0 );
    C( const char *s, const A& t );
    C( const C& t );
    ~C();
    C& operator=( const C& t );
    friend ostream& operator<<( ostream& out, const C& t );
};

// A methods
A::A( const char *l, int t ) {
    label = new char[ strlen(l) + 1 ];
    strcpy( label, l );
    a = t;
}

A::A( const A& t ) {
    label = new char[ strlen(t.label) + 1 ];
    strcpy( label, t.label );
    a = t.a;
}

A::~A() {
    delete[] label;
}

A& A::operator=( const A& t ) {
    /* 若为同一对象,则直接返回,否则会将该对象内容delete,无法复制 */
    if ( this == &t ) {
        return *this;
    }

    delete[] label;  //先释放原内存空间
    label = new char[ strlen(t.label)+1 ];
    strcpy( label, t.label );
    a = t.a;

    return *this;
}

ostream& operator<<( ostream& out, const A& t ) {
    out << "label = " << t.label << ", a = " << t.a << endl;
    return out;
}

// B methods
B::B( const char *c, const char *l, int t ) : A( l, t ) {
    strcpy( color, c );
}

B::B( const char *c, const A& t ) : A(t) {
    strcpy( color, c );
}

ostream& operator<<( ostream& out, const B& t ) {
    out << ( const A& )t;
    out << "color = " << t.color << endl;

    return out;
}

// C methods
C::C( const char *s, const char *l, int t ) : A( l, t ) {
    style = new char[ strlen(s)+1 ];
    strcpy( style, s );
}

C::C( const char *s, const A& t ) : A( t ) {
    style = new char[ strlen(s)+1 ];
    strcpy( style, s );
}

C::C( const C& t ) : A(t) {
    style = new char[ strlen(t.style)+1 ];
    strcpy( style, t.style );
}

C::~C() {
    delete[] style;
}

C& C::operator=( const C& t ) {
    if ( this == &t ) {
        return *this;
    }

    A::operator=(t); //调用A类的赋值函数初始化,相当于 *this = t;
    delete[] style;
    style = new char[ strlen(t.style)+1 ];
    strcpy( style, t.style );

    return *this;
}

ostream& operator<<( ostream& out, const C& t ) {
    out << ( const A& )t;  //类型强转,使用A类的<<运算符重载函数
    out << "style = " << t.style << endl;
    return out;
}

int main() {
    A shirt( "portabelly", 8 );
    B balloon( "red", "Blimpo", 4 );
    C map( "Mercator", "Buffalo", 5 );

    cout << "A:\n" << shirt << endl;
    cout << "B:\n" << balloon << endl;
    cout << "C:\n" << map << endl;

    B balloon2(balloon);
    cout << "balloon2:\n" << balloon2 << endl;

    return 0;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值