继承设计

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类型就可解决此问题。

而且关于char还有一个特殊的语言就是char *,它在C/C++中有专门的语义,既不同于signed char *,也不同于unsigned char *,专门用于指以'\0'为结束的字符串。
在C++中,下列程序是可以通过编译的:
char*p="abcd";

 

 

 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();
}

 

 

posted @ 2019-11-30 16:35  nanaa  阅读(350)  评论(0编辑  收藏  举报