C++程序设计 上机实验(第11章——继承与派生)

1. 共用继承方式、私有继承方式和保护继承方式的对比

#include
using namespace std;
class Student //声明基类
{
public: //基类公用成员
    void get_value() //输入基类数据的成员函数
    {
        cin >> num >> name >> sex;
    }
    void display() //输出基类数据的成员函数
    {
        cout << "num: " << num << endl;
        cout << "name: " << name << endl;
        cout << "sex: " << sex << endl;
    }
private: //基类私有成员
    int num;
    string name;
    char sex;
};

class Student1 :public Student //以public方式声明派生类Student1
{
public:
    void get_value_1() //输入派生类数据
    {
        get_value();
        cin >> age >> addr;
    }
    void display_1()
    {
        display();
        cout << "age: " << age << endl; //引用派生类的私有成员,正确
        cout << "address: " << addr << endl; //引用派生类的私有成员,正确
    }
private:
    int age;
    string addr;
};

int main()
{
    Student1 stud; //定义派生类Student1的对象stud
    stud.get_value_1(); //调用派生类公有成员函数,输出派生类中2个数据成员的值
    stud.display_1(); //调用派生类公有成员函数,输出派生类中2个数据成员的值
    return 0;
}
  • 程序分析:
  • 将程序22行中的继承方式public(公用的)改为private(私有的)或protected(保护的),都能得到以下的运行结果
  • 运行结果:

C++程序设计 上机实验(第11章——继承与派生)_第1张图片
C++程序设计 上机实验(第11章——继承与派生)_第2张图片

2. 对上题的程序修改、补充

#include
using namespace std;
class Student //声明基类
{
public: //基类公用成员
    void get_value() //输入基类数据的成员函数
    {
        cin >> num >> name >> sex;
    }
    void display() //输出基类数据的成员函数
    {
        cout << "num: " << num << endl;
        cout << "name: " << name << endl;
        cout << "sex: " << sex << endl;
    }
protected: //基类保护成员
    int num;
    string name;
    char sex;
};

class Student1 :public Student //以public方式声明派生类Student1
{
public:
    void get_value_1() //输入派生类数据
    {
        get_value();
        cin >> age >> addr;
    }
    void display_1()
    {
        cout << "num: " << num << endl; //引用基类的保护成员
        cout << "name: " << name << endl; //引用基类的保护成员
        cout << "sex: " << sex << endl; //引用基类的保护成员
        cout << "age: " << age << endl; //引用派生类的私有成员
        cout << "address: " << addr << endl; //引用派生类的私有成员
    }
private:
    int age;
    string addr;
};

int main()
{
    Student1 stud; //定义派生类Student1的对象stud
    stud.get_value_1(); //调用派生类公有成员函数,输出派生类中2个数据成员的值
    stud.display_1(); //调用派生类公有成员函数,输出派生类中2个数据成员的值
    return 0;
}

将上题中基类的私有成员改为保护成员,另外将派生类的继承方式指定为public,同时在display1函数中输出基类的保护成员,此时得到的运行结果与上题相同。如果将派生类的继承方式指定为protected,程序也能正常运行,结果不变。但这并不意味着二者可以相互代替,一般情况下,用public和用protected声明继承方式是不等价的。

3. 有以下程序结构,请分析访问属性

class A //A为基类
{
public:
	void f1();
	int i;
protected:
	void f2();
	int j;
private:
	int k;
};

class B :public A //B为A的公用派生类
{
public:
	void f3();
protected:
	int m;
private:
	int n;
};

class C :public B //C为B的公用派生类
{
public:
	void f4();
private:
	int p;
};

int main()
{
	A a1; //a1是派生类A的对象
	B b1; //b1是派生类B的对象
	C c1; //c1是派生类C的对象
}
在基类的访问属性 继承方式 在派生类中的访问属性
public(公用) public(公用) public(公用)
protected(保护) public(公用) protected(保护)
private(私有) public(公用) 不可访问

C++程序设计 上机实验(第11章——继承与派生)_第3张图片

(1)在main函数中能否用b1.i,b1.j和b1.k引用派生类B对象b1中基类A的成员?

  • 可以用b1.i引用对象b1中的基类A的成员i,因为它是公用数据成员。
  • 不能用b1.j引用对象b1中的基类A的成员j,因为它是保护数据成员,在类外不能访问。
  • 不能用b1.k引对象b1中的基类A的成员k,因为它是私有数据成员,在类外不能访问。

(2)派生类B中的成员函数能否调用基类A中的成员函数f1和f2?

  • 可以调用基类A中的成员函数f1和f2,因为f1是公用成员函数,f2是保护成员函数,B对A是公有继承方式,因此它们在派生类中仍然保持原有的访问权限,可以被派生类的成员函数访问。

(3)派生类B中的成员函数能否引用基类A中的数据成员i,j,k?

  • 可以引用基类A中的数据成员i和j,因为它们在派生类中是公用成员和保护成员,可以被派生类的成员函数访问。不可以引用基类A中的数据成员k,它在派生类中是不可访问的成员。

(4)能否在main函数中用c1.i,c1.j,c1.k,c1.m,c1.n,c1.p引用基类A的成员i,j,k,派生类B的成员m,n,以及派生类C的称员p?

  • 可以用c1.i引用对象c1中基类A的成员i,不能用c1.j,c1.k引用基类A的成员j和k,因为它们是保护成员和私有成员,不能被类外访问。也不能访问c1中派生类B的成员m,n,它们也是保护成员和私有成员,不能被类外访问。也不能访问派生类对象c1中的私有成员p

(5)能否在main函数中用c1.f1(),c1.f2(),c1.f3()和c1.f4()调用fl,f2,f3,f4成员函数?

  • 可以调用成员函数f1,f3,f4,它们是公用成员函数。不能调用成员函数f2,因为它是保护成员函数

(6)派生类C的成员函数f4能否调用基类A中的成员函数f1,f2和派生类中的成员函数f3?

  • 可以,f1,f3是公用成员函数,f2是保护成员函数,都可以被派生类C的成员函数调用

4. 有以下程序结构,请分析所有成员在各类的范围内的访问属性

class A //A为基类
{
public:
	void f1();
protected:
	void f2();
private:
	int i;
};

class B :public A //B为A的公用派生类
{
public:
	void f3();
	int k;
private:
	int m;
};

class C :protected B //C为B的保护派生类
{
public:
	void f4();
protected:
	int m;
private:
	int n;
};

class D :private C //D为C的保护派生类
{
public:
	void f5();
protected:
	int p;
private:
	int	 q;
};

int main()
{
	A a1; //a1是派生类A的对象
	B b1; //b1是派生类B的对象
	C c1; //c1是派生类C的对象
	D d1; //d1是派生类D的对象
}
在基类的访问属性 继承方式 在派生类中的访问属性
public(公用) public(公用) public(公用)
protected(保护) public(公用) protected(保护)
private(私有) public(公用) 不可访问
public(公用) protected(保护) protected(保护)
protected(保护) protected(保护) protected(保护)
private(私有) protected(保护) 不可访问
public(公用) private(私有) private(私有)
protected(保护) private(私有) private(私有)
private(私有) private(私有) 不可访问

C++程序设计 上机实验(第11章——继承与派生)_第4张图片
根据以上的分析,可以知道:
(1)在派生类外,可以通过对象调用f5函数,如d1.f5()。其他成员均不能访问。
(2)派生类D的成员函数f5可以访问基类A的员f1和f2,派生类B的成员f3和k,派生类C的成员f4和m,派生类D的成员p和q。
(3)派生类C的成员函f4可以访问基类A的成员f1和f2,派生类B的成员f3和k,派生类C的成员n和m
(4)派生类B的成员函数f3可以访问基类A的成f1和f2,派生类B的成员k和m。
(5)基类A的成员函数f1可以访问基类A的成员f2和i

5. 有以下程序结构,请输出运行时的结果

 #include
using namespace std;
class A //A为基类
{
public: //基类公用成员
	A() { a = 0; b = 0; } //基类默认构造函数
	A(int i) { a = i, b = 0; }
	A(int i, int j) { a = i, b = j; }
	void display() { cout << "a=" << a << " b=" << b; }
private: //基类私有成员
	int a;
	int b;
};

class B :public A //B为A的公用派生类
{
public: //派生类公用成员
	B() { c = 0; } //派生类构造函数
	B(int i) :A(i) { c = 0; }
	B(int i, int j) :A(i, j) { c = 0; }
	B(int i, int j, int k) :A(i, j) { c = k; }
	void display1()
	{
		display();
		cout << " c=" << c << endl;
	}
private: //派生类私有成员
	int c;
};

int main()
{
	B b1; //定义B类对象b1,未给出参数
	B b2(1); //定义B类对象b2,给出一个参数
	B b3(1, 3); //定义B类对象b3,给出两个参数
	B b4(1, 3, 5); //定义B类对象b4,给出三个参数
	b1.display1(); //先调用A类中的成员函数输出a和b的值,接着再输出c的值
	b2.display1();
	b3.display1();
	b4.display1();
	return 0;
}

运行结果:

C++程序设计 上机实验(第11章——继承与派生)_第5张图片

6. 有以下程序结构,请输出运行时的结果

#include
using namespace std;
class A //A为基类
{
public: //基类公用成员
	A() { cout << "constructing A" << endl; } //基类构造函数
	~A() { cout << "destructing A" << endl; } //基类析构函数
};

class B :public A //B是A的公用派生类
{
public: //派生类公用成员
	B() { cout << "constructing B" << endl; } //派生类B的构造函数
	~B() { cout << "destructing B" << endl; } //派生类B的析构函数
};

class C :public B //C是B的公用派生类
{
public: //派生类公用成员
	C() { cout << "constructing C" << endl; } //派生类C的构造函数
	~C() { cout << "destructing C" << endl; } //派生类C的析构函数
};

int main()
{
	C c1;
	return 0;
}

程序分析:

  • 在main函数中,建立C类对象c1,由于没有给出参数,系统会执行默认的派生类C的构造函数。但在执行函数体之前,先要调用其直接基类B的构造函数。同样,在执行构造函数B的函数体之前,要调用基类A的构造函数。输出constructing A,然后返回构造函数B,执行构造函数B的函数体,输出constructing B,然后返回构造函数C,执行构造函数C的函数体,输出constructing C,在建立对象c1之后,由于main函数中已无其他语句,程序结束。
  • 在结束时,要释放对象c1,此时,先调用派生类C的析构函数,根据规定,先执行派生类C的函数体,输出。然后调用派生类C的直接基类B的析构函数,同样,先执行类B的函数体,输出。再调用派生类B的直接基类A的析构函数,执行类A的函数体,输出。

运行结果:

C++程序设计 上机实验(第11章——继承与派生)_第6张图片

7. 分别声明Teacher(教师)类和 Cadre(干部)类,采用多继承方式由这两个类派生出新类Teacher_Cadre(教师兼干部)类。要求:

(1)在两个基类中都包含姓名、年龄、性别、地址、电话等数据成员
(2)在Teacher类中包含数据成员title(职称),Cadre类中还包含数据成员post(职务)。在Teacher_Cadre类中还包含数据成员wages(工资)
(3)对两个基类中的姓名、年龄、性别、地址、电话等数据成员用相同的名字,在引用这些数据成员时,指定作用域
(4)在类体中声明成员函数,在类外定义成员函数
(5)在派生类Teacher_Cadre的成员函数show中调用Teacher类中的display函数,输出姓名、年龄、性别、职称、地址、电话,然后再用cout输出职务与工资

#include
#include
using namespace std;
class Teacher
{
public:
	Teacher(string nam, int a, char s, string tit, string ad, string t); //构造函数
	void display(); //输出姓名、性别、年龄、职称、地址、电话
protected:
	string name; //姓名
	int age; //年龄
	char sex; //性别
	string title; //职称
	string addr; //地址
	string tel; //电话
};

Teacher::Teacher(string nam, int a, char s, string tit, string ad, string t) :
	name(nam), age(a), sex(s), title(tit), addr(ad), tel(t){} //构造函数定义
void Teacher::display()
{
	cout << "name:" << name << endl;
	cout << "age:" << age << endl;
	cout << "sex:" << sex << endl;
	cout << "title:" << title << endl;
	cout << "address:" << addr << endl;
	cout << "tel:" << tel << endl;
}

class Cadre
{
public:
	Cadre(string nam, int a, char s, string p, string ad, string t); //构造函数
	void display();
protected:
	string name; //姓名
	int age; //年龄
	char sex; //性别
	string post; //职务
	string addr; //地址
	string tel; //电话
};

Cadre::Cadre(string nam, int a, char s, string p, string ad, string t):
	name(nam),age(a),sex(s),post(p),addr(ad),tel(t){} //构造函数定义
void Cadre::display()
{
	cout << "name:" << name << endl;
	cout << "age:" << age << endl;
	cout << "sex:" << sex << endl;
	cout << "post:" << post << endl;
	cout << "address:" << addr << endl;
	cout << "tel:" << tel << endl;
}

class Person :public Teacher, public Cadre //派生类(公用继承)
{
public:
	Person(string nam, int a, char s, string tit, string p, string ad, string t, float w);
	void show();
private:
	float wage;
};

Person::Person(string nam, int a, char s, string tit, string p, string ad, string t, float w):
	Teacher(nam,a,s,tit,ad,t),Cadre(nam,a,s,p,ad,t),wage(w){} //构造函数定义
void Person::show()
{
	Teacher::display(); //指定作用域Teacher类
	cout << "post:" << Cadre::post << endl; //指定作用域Cadre类
	cout << "wages:" << wage << endl; //工资
}

int main()
{
	Person person1("Wang-li", 50, 'f', "prof.", "president", "135 Beijing Road,Shanghai", "(021)61234567", 1534.5);
	person1.show();
	return 0;
}

运行结果:

C++程序设计 上机实验(第11章——继承与派生)_第7张图片

8. 在程序中使用继承和组合。在定义Professor类对象prof1时给出所有数据的初值,然后修改prof1的生日数据,最后输出prof1的全部最新数据。

#include
#include
using namespace std;
class Teacher //教师类
{
public:
	Teacher(int, char[], char); //声明构造函数
	void display(); //声明输出函数
private:
	int num;
	char name[20];
	char sex;
};

Teacher::Teacher(int n, char nam[], char s) //定义构造函数
{
	num = n;
	strcpy(name, nam);
	sex = s;
}

void Teacher::display() //定义输出函数
{
	cout << "num:" << num << endl;
	cout << "name:" << name << endl;
	cout << "sex:" << sex << endl;
}

class BirthDate //生日类
{
public:
	BirthDate(int, int, int); //声明构造函数
	void display(); //声明输出函数
	void change(int, int, int); //声明修改函数
private:
	int year;
	int month;
	int day;
};

BirthDate::BirthDate(int y, int m, int d) //定义构造函数
{
	year = y;
	month = m;
	day = d;
}

void BirthDate::display() //定义输出函数
{
	cout << "birthday:" << month << "/" << day << "/" << year << endl;
}

void BirthDate::change(int y, int m, int d) //定义修改函数
{
	year = y;
	month = m;
	day = d;
}

class Professor:public Teacher //教授类
{
	public:
		Professor(int, char[], char, int, int, int, float); //声明构造函数
		void display(); //声明输出函数
		void change(int, int, int); //声明修改函数
private:
	float area; //住房面积
	BirthDate birthday; //定义BirthDate类的对象作为数据成员
};

Professor::Professor(int n,char nam[20],char s,int y,int m,int d,float a):
	Teacher(n,nam,s),birthday(y,m,d),area(a){} //定义构造函数

void Professor::display() //定义输出函数
{
	Teacher::display();
	birthday.display();
	cout << "area:" << area << endl;
}

void Professor::change(int y, int m, int d) //定义修改函数
{
	birthday.change(y, m, d);
}

int main()
{
	Professor prof1(3012, "Zhang", 'f', 1949, 10, 1, 125.4); //定义Professor对象prof1
	cout << endl << "The original data:" << endl;
	prof1.display(); //调用prof1对象的display函数
	cout << endl << "The new data:" << endl;
	prof1.change(1950, 6, 1); //调用prof1对象的change函数
	prof1.display(); //调用prof1对象的dispaly函数
	return 0;
}

运行结果:

C++程序设计 上机实验(第11章——继承与派生)_第8张图片

你可能感兴趣的:(C++程序设计,C++,visualstudio)