继承 之 动态内存分配
2010-08-25 05:51
183 查看
假设基类使用动态内存分配,并重新定义了赋值和复制构造函数
class class_a
{
private:
char* a;
int rating;
public:
class_a(const char* l="null",int r=0);
class_a(const class_a & rs);
virtual ~class_a();
class_a & operator=(const class_a & rs);
...
};
声明中包含了构造函数使用new时需要的特殊方法:析构函数、复制构造函数和重载赋值操作符。详情查看<<关于类隐式成员函数>>
当派生类使用new
class class_b:public class_a
{
private:
char* b; //use new in constructors
public:
...
};
这种情况下,必须为派生类定义显示析构函数、复制构造函数和赋值操作符。
1.析构函数
派生类析构函数自动调用基类的析构函数,故其自身的职责是对派生类构造函数执行工作的进行清理。因此,class_b析构函数必须释放指针 b 管理的内存,并依赖于class_a的析构函数来释放指针 a 管理的内存。
class_a::~class_a(){delete[] a;}
class_b::~class_b(){delete[] b;}
2.复制构造函数
基类定义的复制构造函数如下:
class_a(const class_a & rs)
{
a= new char[std::strlen(re.a)+1];
std::strcpy(a,rs.a);
rating = rs.a;
}
由于class_b的复制构造函数只能访问class_b的数据,因此它必须调用class_a的复制构造函数来处理共享的class_a数据:
class_b::class_b(const class_b & hs):class_a(hs)
{
b = new char[std::strlen(hs.b)+1]
std::strcpy(b,hs.b);
}
3.赋值操作符
基类定义的赋值操作符如下:
class_a & class_a::operator= (const class_a & rs)
{
if(this == &rs)
return *this;
delete [] a;
a = new char[std::strlen(rs.a)+1];
std::strcpy(a,rs.a);
rating=rs.rating;
return *this;
}
派生类的显示赋值操作符必须负责所有继承的class_a基类对象的赋值,可以通过显示调用基类赋值操作符来完成:
class_b & class_a::operator= (const class_b & hs)
{
if(this == &rs)
return *this;
class_a::operator=(hs);
b = new char[std::strlen(hs.b)+1];
std::strcpy(b,hs.b);
return *this;
}
class_a::operator=(hs) 使用函数表示法,而不是操作符表示法,可以使用作用域解析操作符,从而使得赋值操作符被正确的调用。
当基类和派生类都采用动态内存分配时,派生类的析构函数、复制析构函数以及赋值操作符都必须使用相应的基类方法来处理基类元素。对于析构函数,这是自动完成的;对于复制构造函数,这是通过在初始化成员列表中调用基类的复制构造函数来完成的;如果不这样做,将自动调用基类的默认构造函数。对于赋值操作符,是通过使用作用域解析操作符显示地调用基类的赋值操作符来完成的。
class class_a
{
private:
char* a;
int rating;
public:
class_a(const char* l="null",int r=0);
class_a(const class_a & rs);
virtual ~class_a();
class_a & operator=(const class_a & rs);
...
};
声明中包含了构造函数使用new时需要的特殊方法:析构函数、复制构造函数和重载赋值操作符。详情查看<<关于类隐式成员函数>>
当派生类使用new
class class_b:public class_a
{
private:
char* b; //use new in constructors
public:
...
};
这种情况下,必须为派生类定义显示析构函数、复制构造函数和赋值操作符。
1.析构函数
派生类析构函数自动调用基类的析构函数,故其自身的职责是对派生类构造函数执行工作的进行清理。因此,class_b析构函数必须释放指针 b 管理的内存,并依赖于class_a的析构函数来释放指针 a 管理的内存。
class_a::~class_a(){delete[] a;}
class_b::~class_b(){delete[] b;}
2.复制构造函数
基类定义的复制构造函数如下:
class_a(const class_a & rs)
{
a= new char[std::strlen(re.a)+1];
std::strcpy(a,rs.a);
rating = rs.a;
}
由于class_b的复制构造函数只能访问class_b的数据,因此它必须调用class_a的复制构造函数来处理共享的class_a数据:
class_b::class_b(const class_b & hs):class_a(hs)
{
b = new char[std::strlen(hs.b)+1]
std::strcpy(b,hs.b);
}
3.赋值操作符
基类定义的赋值操作符如下:
class_a & class_a::operator= (const class_a & rs)
{
if(this == &rs)
return *this;
delete [] a;
a = new char[std::strlen(rs.a)+1];
std::strcpy(a,rs.a);
rating=rs.rating;
return *this;
}
派生类的显示赋值操作符必须负责所有继承的class_a基类对象的赋值,可以通过显示调用基类赋值操作符来完成:
class_b & class_a::operator= (const class_b & hs)
{
if(this == &rs)
return *this;
class_a::operator=(hs);
b = new char[std::strlen(hs.b)+1];
std::strcpy(b,hs.b);
return *this;
}
class_a::operator=(hs) 使用函数表示法,而不是操作符表示法,可以使用作用域解析操作符,从而使得赋值操作符被正确的调用。
当基类和派生类都采用动态内存分配时,派生类的析构函数、复制析构函数以及赋值操作符都必须使用相应的基类方法来处理基类元素。对于析构函数,这是自动完成的;对于复制构造函数,这是通过在初始化成员列表中调用基类的复制构造函数来完成的;如果不这样做,将自动调用基类的默认构造函数。对于赋值操作符,是通过使用作用域解析操作符显示地调用基类的赋值操作符来完成的。
相关文章推荐
- C++之继承和动态内存分配
- 继承 之 动态内存分配
- C++之继承和动态内存分配
- C++ 继承和动态内存分配
- C++中继承与动态内存分配
- (一四二)继承和动态内存分配
- 继承和动态内存分配
- C++ 学习(继承和动态内存分配)
- 条款32:确定你的public继承塑模出is-a关系
- 对象--继承
- 使用模板来解决接口继承问题
- Hibernate实体对象继承策略
- java学习记录笔记--继承,super,Object类
- js--面向对象--非构造函数的继承
- 1.为什么需要继承?如何继承?继承到什么? 2.方法的重载与重写的区别 3.类型的自动转换和强制转换 4.子类特有的方法的调用规则 5.子类重写的方法的调用规则 6.多态的理解 7.面向对象的三大特征
- scala学习-Scala class的构造方法与继承
- Java 8 默认方法和多继承
- javascript玩转继承(三)
- UML 继承、实现、依赖、关联、聚合、组合的联系与区别
- 虚继承及无关