7-5 定义一个基类 Shape,在此基础上派生出 Rectangle 和 Circle,二者都有 getArea()函数计算对象的面积。使用 Rectangle类创建一个派生类 Square。
#include
using namespace std;
class Shape {
public:
virtual float getArea() = 0; //纯虚函数
Shape() { } //构造函数不能是虚函数
virtual ~Shape() {} //虚析构函数,先调用释放派生类的空间,然后再释放基类的内存空间。
};
class Rectangle:public Shape{
private:
float length;
float wide;
public:
Rectangle(float l,float w){
length=l;
wide=w;
}
virtual float getArea(){
return length*wide;
}
};
class Circle:public Shape{
private:
float R;
public:
Circle(float r){
R=r;
}
float getArea(){
return 3.14*R*R;
}
};
class Square:public Rectangle{
public:
Square(float x):Rectangle(x,x){}
};
int main( )
{
Shape *ps;
ps = new Circle( 5 );
cout << "The area of the Circle is " << ps->getArea() << endl;
delete ps;
ps = new Rectangle( 5, 6 );
cout << "The area of the Rectagle is " << ps->getArea() << endl;
delete ps;
ps = new Square( 5 );
cout << "The area of the Square is " << ps->getArea() << endl;
delete ps;
return 0;
}
- 一旦基类中有带参数的构造函数,派生类中则必须有显式传参的派生类构造函数,来实现基类中参数的传递,完成初始化工作。
- 纯虚函数声明之后,基类中就可以不再给出函数的实现部分。纯虚函数的函数体由派生类给出。该纯虚函数所在的类是抽象类,不能直接进行实例化。
- 构造函数不能是虚函数。
- 虚析构函数实现了析构函数的多态,能避免内存泄露,防止派生类对象中动态分配的内存空间没有得到释放。这个时候多态效应出现,会先调用释放派生类的空间,然后再释放基类的内存空间。
7-6 定义一个哺乳动物类 Mammal,再由此派生出狗类 Dog,定义一个 Dog 类的对象,观察基类与派生类的构造函数和析构函数的调用顺序。
#include
using namespace std;
class Mammal{
private:
int age;
double weight;
public:
Mammal(){cout << "Constructor in Mammal.\n";}
~Mammal(){cout << "Destructor in Mammal.\n";}
void setAge(int a) {
age=a;
}
int getAge(){
return age;
}
void setWeight(double w) {
weight=w;
}
double getWeight(){
return weight;
}
};
class Dog:public Mammal{
private:
string color;
public:
Dog(){cout << "Constructor in Dog.\n";}
~Dog(){cout << "Destructor in Dog.\n";}
void setColor(string s){
color = s;
}
string getColor(){
return color;
}
void speak(){cout << "Dog sound wang,wang,wang!\n";}
};
int main() {
Dog d;
d.setAge( 4 );
d.setWeight( 12 );
d.setColor( "Black" );
cout << d.getAge() << endl;
cout << d.getWeight() << endl;
cout << d.getColor() << endl;
d.speak();
return 0;
}
- 构造函数调用顺序:基类->派生类
- 析构函数调用顺序:派生类->基类
7-7 定义一个基类及其派生类,在构造函数中输出提示信息,构造派生类的对象,观察构造函数的执行情况。
#include
using namespace std;
class Clock
{
private:
int H;
int M;
int S;
public:
Clock()
{
cout<<"Clock's Constructor Called!"<
7-8 定义一个 Document类,有数据成员 name,从 Document派生出 Book 类,增加数据成
员 pageCount。
#include
#include
using namespace std;
class Document{
public:
Document(string aname):name(aname){
cout << "Constructing Document" << endl;
}
~Document(){
cout << "Destructing Document" << endl;
}
protected:
string name; //保护成员,派生类可访问到
};
class Book:public Document{
public:
Book(string aname,int apageCount):Document(aname),pageCount(apageCount){
cout << "Constructing Book" << endl;}
~Book(){
cout << "Destructing Book" << endl;
}
void print();
private:
int pageCount;
};
void Book::print()
{
cout<
派生类的成员函数可以访问基类的保护成员或公有成员。故代码中将基类Document的成员name设置为保护成员,。
Book这样Book类就继承了 Document类的成员,也就实现了代码的重用,同时通过新增成员pageCount,加入了自身的独有特征,达到了程序的扩充。
7-9 定义一个基类 Base,有两个公有成员函数 fn1(),fn2(),私有派生出 Derived 类,如何通过 Derived 类的对象调用基类的函数 fn1()?
#include
using namespace std;
class Base{ //基类Base
public:
int fn1(){return 1;}
int fn2(){return 2;}
};
class Derived:private Base{ //私有派生类Derived;
public:
int fn1(){cout<
如果要访问被隐藏的成员,就需要使用作用域分辨符和基类名来限定。
7-10 定义一个 Object类,有数据成员 weight及相应的操作函数,由此派生出 Box 类,增加数据成员 height和 width 及相应的操作函数,声明一个Box对象,观察构造函数与析构函数的调用顺序。
#include
using namespace std;
class object {
private:
int weight;
public:
object() {
weight=0;
cout << "obj的构造函数" << endl;
}
void setWight(int w){
weight=w;
}
~object() {
cout << "obj的析构函数" << endl;
}
};
class box :public object{
private:
int height, width;
public:
box() {
height=width=0;
cout << "box的构造函数" << endl;
}
void setHeight(int h){
height=h;
}
void setWidth(int w){
width=w;
}
~box() {
cout << "box的析构函数" << endl;
}
};
int main()
{
box b;
return 0;
}
7-11 定义一个基类 BaseClass,从它派生出类 DerivedClass。BaseClass 有成员函数fn1(),fn2(),DerivedClass 也有成员函数 fn1(),fn2()。在主函数中声明一个DerivedClass的对象,分别用 DerivedClass的对象以及 BaseClass和 DerivedClass 的指针来调用fn1(),fn2(),观察运行结果。
#include
using namespace std;
class BaseClass{
public:
void fn1(){
cout<<"基类的 fn1()"<fn1();
p1->fn2();
DerivedClass *p2=&d;
p2->fn1();
p2->fn2();
return 0;
}
本专栏为本人大二C++课程的习题作业和一些学习经验的分享,供大家参考学习。如有侵权请立即与我联系,我将及时处理。
参考书籍为:C++语言程序设计 第五版 -清华大学出版社- 郑莉,董渊、C++语言程序设计 第五版 -清华大学出版社- 郑莉,董渊(学生用书)
编译环境:Visual Studio 2019、Dev-C++
欢迎关注我的微信公众号,分享一些有趣的知识:程序猿的茶水间