继承与动态内存分配
在基类或派生类中含有指针时,要考虑内存分配情况(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;
}