对于C++中基类含有new创建的数据成员,派生类中不存在或者存在new创建的数据成员。下面的代码说明怎样处理不同情况下的复制构造函数和赋值运算符重载的设计问题(内容比较杂乱易忘)
//statement.h
#ifndef _STATEMENT_H_
#define _STATEMENT_H_
#include<iostream>
using namespace std;
//声明一个抽象基类(包含至少一个纯虚函数)不能用来具体化一个对象
class baseDMA
{
private: //如果是protected对于派生类来说相当于public,对于类外来说是private
char *label;
int rating;
int num;//用来测试纯虚函数
public:
baseDMA(char *c = "null", int r = 0, int n = 0);
baseDMA(const baseDMA &object);//对于含有指针的数据成员需要显式创建深度复制构造函数
baseDMA& operator=(const baseDMA &object);//同样需要重载显式赋值运算符
virtual ~baseDMA();//将基类析构函数声明为虚函数,以至于当利用基类指针或引用指向派生类时可以正确调用派生类析构函数
virtual void change_num(const int &n) = 0;//声明为纯虚函数,这样就不能利用baseDMA类来创建对象
//函数change_num()用派生类来实现接口
virtual void show() const;
int get_num() const{ return num; }
void reset_num(const int &n){ num = n; }
friend ostream & operator<<(ostream &os, const baseDMA &object);
protected:
struct Formatting
{
ios_base::fmtflags flag;
streamsize pr;
};
Formatting SetFormat() const;
void Restore(Formatting &f) const;
};
class lacksDMA :public baseDMA
{
private:
enum{ COL_LEN = 40 };
char color[COL_LEN];
public:
lacksDMA(char *c = "null", int r = 0, int n = 0, const char *col = "blank");
lacksDMA(const baseDMA &object, const char *col = "blank");
friend ostream& operator<<(ostream &os, const lacksDMA &object);
virtual void show() const;
virtual void change_num(const int &n);
~lacksDMA(){};
};
class hasDMA :public baseDMA
{
private:
char *style; //对于基类含有new数据成员和派生类也含有new数据成员的
//必须同时为两个类构造深度复制构造函数以及重载深度赋值运算符
public:
hasDMA(char *c = "null", const int r = 0, const int n = 0, const char *s = "null");
hasDMA(const baseDMA &object, const char *s = "null");
hasDMA(const hasDMA &h);
hasDMA& operator=(const hasDMA &h);
virtual void show() const;
virtual void change_num(const int &n);
friend ostream& operator<<(ostream &os, const hasDMA &h);
~hasDMA();
};
#endif //_STATEMENT_H_
//define.cpp
/**
*Copyright U+00A9 2018 XXXXXX. All Right Reserved.
*Filename:
*Author:XXXXXX
*Date:2018.12.01
*Version:VS 2013
*Description:
**/
#include<iostream>
#include<cstring>
//#include<cstdlib>
#include"statement.h"
using namespace std;
baseDMA::baseDMA(char *c, int r, int n)
{
label = new char[strlen(c)+1];
strcpy(label, c);
rating = r;
num = n;
}
baseDMA::baseDMA(const baseDMA &object)
{
label = new char[strlen(object.label) + 1];
strcpy(label, object.label);
rating = object.rating;
num = object.num;
}
baseDMA& baseDMA::operator=(const baseDMA &object)
{
if (this == &object)
return *this;
delete [] label;
label = new char[strlen(object.label) + 1];
strcpy(label, object.label);
rating = object.rating;
num = object.num;
return *this;
}
baseDMA::~baseDMA()
{
delete [] label;
}
void baseDMA::show() const
{
Formatting f = SetFormat();
cout << "label:" << label <<
" rating:" << rating <<
" num:" << num << endl;
Restore(f);
}
ostream & operator<<(ostream &os, const baseDMA &object)
{
os << "label:" << object.label <<
" rating:" << object.rating <<
" num:" << object.num << endl;
return os;
}
baseDMA::Formatting baseDMA::SetFormat() const//记住保护成员结构体也要加限定
{
Formatting f;
f.flag = cout.setf(ios_base::fixed, ios_base::floatfield);
f.pr = cout.precision(2);
return f;
}
void baseDMA::Restore(Formatting &f) const
{
cout.setf(f.flag, ios_base::floatfield);
cout.precision(f.pr);
}
lacksDMA::lacksDMA(char *c, int r, int n, const char *col):baseDMA(c,r,n)
{
strncpy(color,col,39);
color[COL_LEN - 1] = '\0';
}
lacksDMA::lacksDMA(const baseDMA &object, const char *col) :baseDMA(object)
{
strncpy(color, col, 39);
color[COL_LEN - 1] = '\0';
}
ostream& operator<<(ostream &os, const lacksDMA &object)
{
os<< dynamic_cast<const baseDMA&>(object);
os << "color:" << object.color << endl;
return os;
}
void lacksDMA::show() const
{
Formatting f = SetFormat();
baseDMA::show();
cout << "color:" << color << endl;
Restore(f);
}
void lacksDMA::change_num(const int &n)
{
reset_num(n);
}
hasDMA::hasDMA(char *c, const int r, const int n, const char *s) :baseDMA(c,r,n)
{
style = new char[strlen(s) + 1];
strcpy(style, s);
}
hasDMA::hasDMA(const baseDMA &object, const char *s) :baseDMA(object)
{
style = new char[strlen(s) + 1];
strcpy(style, s);
}
hasDMA::hasDMA(const hasDMA &h) : baseDMA(h)
{
style = new char[strlen(h.style) + 1];
strcpy(style, h.style);
}
hasDMA& hasDMA::operator=(const hasDMA &h)
{
if (this == &h)
return *this;
baseDMA::operator=(h);/*当基类和派生类均包含new创建的数据成员时
,重载赋值运算符需要用到基类重载去实现基类数据赋值*/
delete[] style;
style = new char[strlen(h.style) + 1];
strcpy(style, h.style);
return *this;
}
void hasDMA::show() const
{
Formatting f = SetFormat();
baseDMA::show();
cout << "style:" << style << endl;
Restore(f);
}
void hasDMA::change_num(const int &n)
{
reset_num(2 * n);
}
ostream& operator<<(ostream &os, const hasDMA &h)
{
os << dynamic_cast<const baseDMA&>(h);
os << "style:" << h.style << endl;
return os;
}
hasDMA::~hasDMA()
{
delete[] style;
}
//main.cpp
/**
*Copyright U+00A9 2018 XXXXXX. All Right Reserved.
*Filename:
*Author:XXXXX
*Date:2018.12.01
*Version:VS 2013
*Description:
**/
#include<iostream>
#include"statement.h"
#include<windows.h>
using namespace std;
int main()
{
lacksDMA obj1("nuaa", 12, 3, "red");
cout << "the original obj1 is " << obj1;
lacksDMA *obj2=new lacksDMA("zhonghua",10,1,"white");
cout << "the original obj2 is ";
obj2->show();
delete obj2;
lacksDMA obj3;
cout << "the original obj3 is " << obj3;
obj3 = obj1;
cout << "Later for obj3 = obj1, obj3 is " << obj3;
cout << "obj3.show() is ";
obj3.show();
cout << "Reset obj3'num=5 is ";
obj3.change_num(5);
cout << "Later for obj3.change_num(5), obj3 is " << obj3;
hasDMA obj4 = hasDMA("ZTE", 18, 4, "fashion");
cout << "the original obj4 is " << obj4;
hasDMA obj5;
obj5 = obj4;
cout << "Later for obj5 = obj4, obj5 is " << obj5;
cout << "obj5.show() is ";
obj5.show();
cout << "Reset obj5'num=10 is ";
obj5.change_num(5);
cout << "Later for obj5.change_num(5), obj3 is " << obj5;
system("pause");
return 0;
}
程序运行结果如下图