1.回顾类和对象的创建
定义学生类Student,包含私有数据成员:num(学号)、name(姓名,字符数组)、age(年龄);公有成员函数:Student(构造函数)、~Student(析构函数),使用构造函数为Student类对象的数据成员赋值(name使用动态内存分配),在析构函数中释放动态分配的内存,显示函数display(显示学生信息)。
法一:
#include<iostream>
#include<string>
using namespace std;
class Student {
private:
long num;
char* name;
int age;
public:
Student() {}
Student(long nu, char* na, int a) :num(nu), name(na), age(a) {}
~Student() {}
void display() {
cout << "学号:" << num << " " << endl << "姓名:" << name << endl << "年龄:" << age << endl;
}
};
int main() {
char ch[] = "李丽";
Student* ptr = new Student();//①
ptr = new Student(3018314, ch, 18);//②
Student* ptr1 = new Student(2018314, ch, 18);//③
ptr->display();//这个指针对应①②,需要无参数的构造函数
cout << endl;
ptr1->display();//这个指针对应③,调用声明的有参构造函数即可
return 0;
}

法二:(多条信息)
#include <iostream>
#include <string>
using namespace std;
class student
{
private:
int num;
char name[30];
int age;
public:
student(int nu, const char* na, int ag)
{
num = nu;
strcpy_s(name, na);
age = ag;
}
~student() {}
void display(student** ss, int total) {
student* sp = ss[0];
int i = 0;
while (i < total)
{
cout << "(" << i + 1 << ") " << sp->num << " " << sp->name << " " << sp->age << endl;
i++;
sp = ss[i];
}
sp = NULL;
}
int main()
{
student* ss[4];
for (int i = 0; i < 4; i++)
{
ss[i] = NULL;
}
ss[0] = new student(2018311, "李丽", 18);
ss[1] = new student(2018312, "张三", 18);
ss[2] = new student(2018313, "王明", 19);
ss[3] = new student(2018314, "李四", 19);
ss[0]->display(ss, 4);
return 0;
}

2、思考代码
#include<iostream>
#include<string>
using namespace std;
class person { //person基类
private:
string name;
protected:
int age;
public:
void printname();
void setname(string);
person() {
name = "基类test";
cout << "name=" << name << " 基类构造函数执行" << endl;
}
person(string name1) {
name = name1;
cout<<"name="<<name<<" 基类构造函数执行"<<endl;
}
~person() {
cout<<"name="<<name<<" 基类person析构函数执行"<<endl;
}
};
void person::printname() { cout << "基类name=" << name << endl; }
void person::setname(string name1) { name = name1; }
class student :public person {//student 继承person 是派生类
private:
int no;
float score;
person p1;
protected:
string sex;
public:
void output();
student():person("mm"),p1("4")
{
no = 1;
score = 80.0;
age = 20;
cout << "no=" << no << " 派生类构造函数执行" << endl;
}
~student() {
cout<<"no="<<no<<" "<<"派生类析构函数"<<endl;
}
};
void student::output() {
printname();
cout << "age=" << age << endl;
}
void main() {
student st; //说明在创建st对象时,调用了哪个构造函数
//是否调用了基类构造函数?如果是,调用的是哪个基类的构造函数
cout << "st----" << endl;
st.printname();
}

总结:
析构函数的调用顺序与构造函数相反。
构造函数的调用从基类开始再到派生类,“从外到里”;
而析构函数“从里到外”,先调用派生类的析构函数,再一步步到基类。即派生类本身的析构函数->对象成员析构函数->基类析构函数。
3、编程
定义一个Teacher类,包含私有数据成员int num、string name、char sex,构造函数Teacher()和有参构造函数Teacher(int num,string name,char sex),成员函数input实现数据成员的输入,成员函数数output实现数据成员输出到屏幕上。定义Professor类,包含私有数据成员int rank,并公有继承Teacher类;通过构造函数初始化所有数据成员(包括继承来的数据成员),成员函数Pinput实现所有数据成员的输入(包括继承的数据成员),Pouput实现所有数据成员的输出。
#include<iostream>
#include<string>
using namespace std;
class Teacher {
private:
int num;
string name;
char sex;//string
public:
Teacher() {}
Teacher(int nu, string na, char s) :num(nu), name(na), sex(s) {}
void input() {
cout << "请输入学号,姓名,性别:" << endl;
cin >> num >> name >> sex;
}
void output() {
cout << "学号:" << num << " " << "姓名:" << name << " " << "性别:" << sex << endl;
}
};
class Professor :public Teacher {
private:
int rank;
public:
Professor() {}
Professor(int n1, string n2, char a1, int r) :Teacher(n1,n2,a1), rank(r) {} //Professor() {} //在派生类构造函数的初始化列表里调用基类的构造函数 //Professor(int rank) { //Teacher();派生类的构造函数中继承基类的构造函数 //this->rank = rank; // } //void Pinput(); //void Poutput();
void Pinput() {
input();
cout << "请输入排名:" << endl;
cin >> rank;
}
void Poutput() {
output();
cout << "排名:" << rank;
}
};
int main() {
Professor s;
s.Pinput();
s.Poutput();
return 0;
}
注意:
char型数据是计算机编程语言中只可容纳单个字符的一种基本数据类型。
声明sex 为char类型,所以性别输入“女”会多占字符,导致rank无法输入,
将其声明为string类型就可解决此问题。

4、多继承应用
派生类名::派生类名(参数表:基类1的形参,基类2的形参,……,基类n的形参,本类的形参):基类名1(基类1的形参),基类名2(基类2的形参),……,基类名n(基类名n的形参)
{
本类成员初始化赋值语句;
}
例:
#include<iostream>
#include<string>
using namespace std;
class A {
private:
int a;
public:
A(int x) { a = x; }
void setA(int x) { a = x; }
void showA() { cout << "a=" << a << endl; }
};
class B {
private:
int b;
public:
B(int x) { b = x; }
void setB(int x) { b = x; }
void showB() { cout << "b=" << b << endl; }
};
class C :public A, private B //公有继承A,私有继承B
{
private:
int c;
public:
C(int a, int b, int c1) :A(a), B(b) //派生类构造函数初始化
{
c = c1;
}
void setC(int x, int y) {
c = x;
setB(y); //通过B类的成员函数setB()为B类的私有成员b赋值
}
void showC() { cout << "c=" << c << endl; }
void showABC() {
showA(); //能否改成 cout<<"a="<<a<<endl;
showB(); //能否改成 cout<<"b="<<b<<endl;
cout << "c=" << c << endl;
}
};
void main() {
C obj(1, 2, 3);
cout << "显示a,b,c" << endl;
obj.showABC();
/*cout<<"显示a"<<endl;
obj.showA();
cout<<"显示b"<<endl;
obj.showB(); */
}
在类C中的showABC()函数中,能否将
showA(); 改成 cout<<"a="<<a<<endl;
showB(); 改成 cout<<"b="<<b<<endl;
答:不能,因为a,b是基类的私有成员,在类C中不可访问。
5、编程实现:(多继承)
(1)定义“点”类Point。包含数据成员x,y(分别表示点的横纵坐标),具有构造函数;成员函数void showpoint()输出x,y,int getx()、int gety()分别返回x、y的值,void setxy()给x,y赋值。
(2)定义半径类Radius。包含数据成员r,具有构造函数;成员函数void setr(int r1)设置r的值,int getr()返回r的值。
(3)由Point类、Radius类派生出圆类Circle,在其构造函数中给基类数据成员赋值,成员函数double area()返回圆的面积,void shouwcircle()输出点的坐标和圆的面积。
(4)在main函数中,定义Circle类的对象,并调用setxy,setr, showcircle函数。
#include<iostream>
using namespace std;
#define PI 3.141592
class Point {
private:
int x, y;
public:
Point() {}
void showpoint() {
cout << "x=" << x << endl;
cout << "y=" << y << endl;
}
int getx()
{
return x;
}
int gety()
{
return y;
}
void setxy(int xx, int yy)
{
x = xx;
y = yy;
}
};
class Radius {
private:
int r;
public:
Radius() {}
void setr(int r1) {
r = r1;
}
int getr()
{
return r;
}
};
class Circle :public Point, public Radius { //多继承
public:
Circle() {}
Circle(int xx, int yy) {
setxy(xx, yy);
}
double area() {
return getr() * getr() * PI;
}
void showcircle() {
cout << "圆心坐标为:" << "(" << getx() << "," << gety() << ")" << endl;
cout << "圆的面积为:" << area() << endl;
}
};
void main() {
int x, y;
int r;
cout << "输入圆心坐标x y:";
cin >> x >> y;
cout << "输入半径r:";
cin >> r;
Circle c;
c.setxy(x, y);
c.setr(r);
c.showcircle();
}