C++语言程序设计第五版 - 郑莉(第七章课后习题)

第7章  继承与派生

7-5 定义一个基类 Shape,在此基础上派生出 Rectangle 和 Circle,二者都有 getArea()函数计算对象的面积。使用 Rectangle类创建一个派生类 Square。

#include <iostream>
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 <iostream>
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<iostream>
using namespace std;
class Clock
{
private:
    int H;
    int M;
    int S;
public:
    Clock()
    {
        cout<<"Clock's Constructor Called!"<<endl;
    }
  
};
  
class AlarmClock:public Clock
{
private:
    int AH;
    int AM;
public:
    AlarmClock()
    {
        cout<<"AlarmClock's Constructor Called!"<<endl;
    }
  
};
  
int main()
{
    AlarmClock A;
  
    return 0;
}

7-8 定义一个 Document类,有数据成员 name,从 Document派生出 Book 类,增加数据成

员 pageCount。

#include <iostream>
#include <string>
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<<name<<": "<<pageCount<<"页"<<endl; 
}
int main() 
{
	Document a("骆驼祥子"); 
	Book b("朝花夕拾",200);
	b.print(); 
    return 0;
}

 派生类的成员函数可以访问基类的保护成员或公有成员。故代码中将基类Document的成员name设置为保护成员,。

Book这样Book类就继承了 Document类的成员,也就实现了代码的重用,同时通过新增成员pageCount,加入了自身的独有特征,达到了程序的扩充。

7-9 定义一个基类 Base,有两个公有成员函数 fn1(),fn2(),私有派生出 Derived 类,如何通过 Derived 类的对象调用基类的函数 fn1()?

#include <iostream>
using namespace std;

class Base{  //基类Base
	public:
		int fn1(){return 1;}
		int fn2(){return 2;}
};
class Derived:private Base{  //私有派生类Derived;
	public:
		int fn1(){cout<<Base::fn1()<<endl;}//返回Base类中函数fn1,以调用fn1;
		int fn2(){cout<<Base::fn2()<<endl;}//返回Base类中函数fn2,以调用fn2;
};
int main(){
	Derived a;//定义一个参数a;
	a.fn1(); //调用Derived类中的fn1函数,fn1返回值调用Base类的fn1函数;
	a.fn2(); //调用Derived类中的fn2函数,fn2返回值调用Base类的fn2函数;
	return 0;
}

 如果要访问被隐藏的成员,就需要使用作用域分辨符和基类名来限定。

7-10 定义一个 Object类,有数据成员 weight及相应的操作函数,由此派生出 Box 类,增加数据成员 height和 width 及相应的操作函数,声明一个Box对象,观察构造函数与析构函数的调用顺序。

#include<iostream>
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<iostream>
using namespace std;

class BaseClass{
	public:
   		void fn1(){
    	    cout<<"基类的 fn1()"<<endl;
    	}
    	void fn2(){
        	cout<<"基类的 fn2()"<<endl;
    	}
};
class DerivedClass:public BaseClass{
	public:
    	void fn1(){
        	cout<<"派生类的 fn1()"<<endl;
    	}
    	void fn2(){
        	cout<<"派生类的 fn2()"<<endl;
    	}
};
int main()
{
    DerivedClass d;
    d.fn1();
    d.fn2();
    
    BaseClass *p1 =&d;
    p1->fn1();
    p1->fn2();
    
    DerivedClass *p2=&d;
    p2->fn1();
    p2->fn2();
    
    return 0;
}

本专栏为本人大二C++课程的习题作业和一些学习经验的分享,供大家参考学习。如有侵权请立即与我联系,我将及时处理。


参考书籍为:C++语言程序设计 第五版 -清华大学出版社- 郑莉,董渊、C++语言程序设计 第五版 -清华大学出版社- 郑莉,董渊(学生用书)

编译环境:Visual Studio 2019、Dev-C++

欢迎关注我的微信公众号,分享一些有趣的知识:程序猿的茶水间

  • 12
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值