C++学习之路 day8

Day8 知识点:

1.赋值兼容

赋值兼容只能发生在公有派生继承的父子关系中。

a) 子类对象(派生类)赋给父类(基类)的对象

b) 子类对象赋给父类的引用

c) 子类对象的地址赋给父类的指针


实验代码:

#include <iostream>

using namespace std;

class shape
{
public:
    shape(int x = 0, int y = 0)
        :_x(x),_y(y){}

    void draw()
    {
        cout<<"drawfrom"<<"("<<_x<<","<<_y<<")"<<endl;
    }
protected:
    int _x;
    int _y;
};

class circle:public shape
{
public:
    circle(int x = 0, int y = 0, int r = 0)
        :shape(x,y),_radius(r){}

    void draw()
    {
        cout<<"drawfrom"<<"("<<_x<<","<<_y<<")";
        cout<<" radius = "<<_radius<<endl;
    }

    void func()
    {
        cout<<"------------------"<<endl;
    }

private:
    int _radius;

};

int main()
{
    shape s(1,2);
    s.draw();

    circle c(1,2,3);
    c.draw();
    c.func();

    shape s1 = c;       //派生类对象赋给基类对象
    s1.draw();

    shape &rc = c;      //派生类对象赋给基类的引用
    rc.draw();

    shape *pc = &c;     //派生类对象的地址赋给指向基类的指针
    pc->draw();

    return 0;
}




2.多态:由继承产生的相关的不同的类,对同一消息做出的不同响应。

静多态,编译阶段决定的

#include <iostream>

using namespace std;

void func(int a, float b)
{
    cout<<"void func(int a, float b)"<<endl;
}

void func(float a, int b)
{
    cout<<"void func(float a, int b)"<<endl;
}



int main()
{
    func(1,3.0);        //在编译阶段就完成函数的倾轧
    func(3.0,1);

    return 0;
}


动多态,运行阶段决定的

实现条件:

1) 父类中有虚函数(在函数声明前virtual定义时不需要)

2) 子类中覆写(override)了父的虚函数,根据需要重新定义函数体

{

a) overload重载 同一作用域中,函数名相同,参数列表不同;

b) shadow 发生在父子类中的同名成员(函数或数据,如果是函数只要同名就会构成shadow);

c) override  发生在父子类中,父类中函数有virtual声明的函数,子类中同参同名同返回

   }

3) 成员函数被声明为虚函数后,其子类中的完全相同的函数也是虚函数。可以加virtual以示清晰(也可不加)

4) 定义一个父类的指针,将子类对象地址赋给父类的指针,通过该指针调用虚函数,调用的就是所指向子类中的虚函数

5) 子类中覆写的函数可以是任意访问类型,依需求而定。

实验代码:

#include <iostream>


using namespace std;

class shape
{
public:
    shape(int x = 0, int y = 0)
        :_x(x),_y(y){}

    virtual void draw()
    {
        cout<<"drawfrom"<<"("<<_x<<","<<_y<<")"<<endl;
    }
protected:
    int _x;
    int _y;
};

class Circle:public shape
{
public:
    Circle(int x = 0, int y= 0, int r = 0)
        :shape(x,y),_radius(r){}

    virtual void draw()
    {
        cout<<"drawfrom"<<"("<<_x<<","<<_y<<")";
        cout<<" _radius ="<<_radius<<endl;
    }

private:
    int _radius;
};

class Rec:public shape
{
public:
    Rec(int x = 0, int y = 0,int len = 0, int wid = 0 )
        :shape(x,y),_len(len),_wid(wid){}

    virtual void draw()
    {
        cout<<"drawfrom"<<"("<<_x<<","<<_y<<")";
        cout<<" _len ="<<_len<<" _wid= "<<_wid<<endl;
    }
private:
    int _len;
    int _wid;
};


int main()
{
    Circle c(1,2,3);
    c.draw();

    Rec r(1,2,3,4);
    r.draw();

    shape *ps = NULL;

    int choice;


    while(1)
    {
        scanf("%d",&choice);
        switch(choice)
        {
            case 1:
                ps = &c;
                ps->draw();
            break;
            case 2:
                ps = &r;
                ps->draw();
            break;
        }
    }


    return 0;
}


3.

virtual void draw() = 0;纯虚函数格式

1.含有纯虚函数的类,称为抽象基类,不可实列化。即不能创建对象,存在的意义就是被
继承,提供族类的公共接口,java 中称为 interface;

2. 纯虚函数只有声明,没有实现,被“初始化”为 0;

3. 如果一个类中声明了纯虚函数,而在派生类中没有对该函数定义,则该虚函数在派生类
中仍然为纯虚函数,派生类仍然为纯虚基类。


实例代码:

#include <iostream>


using namespace std;





class shape
{
public:
    shape(int x = 0, int y = 0)
        :_x(x),_y(y){}

    virtual void draw() = 0;

protected:
    int _x;
    int _y;
};

class Circle:public shape
{
public:
    Circle(int x = 0, int y= 0, int r = 0)
        :shape(x,y),_radius(r){}

    virtual void draw()
    {
        cout<<"drawfrom"<<"("<<_x<<","<<_y<<")";
        cout<<" _radius ="<<_radius<<endl;
    }

private:
    int _radius;
};

class Rec:public shape
{
public:
    Rec(int x = 0, int y = 0,int len = 0, int wid = 0 )
        :shape(x,y),_len(len),_wid(wid){}

    virtual void draw()
    {
        cout<<"drawfrom"<<"("<<_x<<","<<_y<<")";
        cout<<" _len ="<<_len<<" _wid= "<<_wid<<endl;
    }
private:
    int _len;
    int _wid;
};


int main()
{
    Circle c(1,2,3);
    Rec r(3,4,5,6);

    shape *ps = &c;
    ps->draw();

    ps = &r;
    ps->draw();


    return 0;
}



4.虚析构(在析构器前加virtual)

目的:为了析构完全,在delete父类指针的时候,会调用子类的析构函数,实现完整析构。

 使用方法:当一个类中有虚函数的时候,将其析构函数一并加上virtual

实验代码:

//animal.h
#ifndef ANIMAL_H
#define ANIMAL_H


class Animal
{
public:
    Animal();
    virtual ~Animal();          //如果不加virtual,在释放堆内存的时候只会对Animai进行析构,
    virtual void voice() = 0;   //Animal指针指向的内存不会自动完成析构
};

#endif // ANIMAL_H
//cat.h
#ifndef CAT_H
#define CAT_H
#include "animal.h"

class Cat:public Animal
{
public:
    Cat();
    ~Cat();
    virtual void voice();
};

#endif // CAT_H
//dog.h
#ifndef DOG_H
#define DOG_H
#include "animal.h"

class Dog:public Animal
{
public:
    Dog();
    ~Dog();
    void voice();
};

#endif // DOG_H
//animal.cpp
#include "animal.h"
#include <iostream>

using namespace std;


Animal::Animal()
{
    cout<<"Animal()"<<endl;
}

Animal::~Animal()
{
    cout<<"~Animal()"<<endl;
}
//cat.cpp
#include "cat.h"
#include <iostream>

using namespace std;

Cat::Cat()
{
    cout<<"Cat()"<<endl;
}

Cat::~Cat()
{
    cout<<"~Cat()"<<endl;
}

void Cat::voice()
{
    cout<<"I am a cat,miao miao miao"<<endl;
}
//dog.cpp
#include "dog.h"
#include <iostream>

using namespace std;

Dog::Dog()
{
    cout<<"Dog()"<<endl;
}

Dog::~Dog()
{
    cout<<"~Dog()"<<endl;
}

void Dog::voice()
{
    cout<<"I am a dog,wang wang wang"<<endl;
}
//main.cpp
#include <iostream>
#include "animal.h"
#include "cat.h"
#include "dog.h"

using namespace std;

int main()
{
    Dog d;
    Cat c;
    Animal *a1 = &d;
    Animal *a2 = &c;

    a1->voice();
    a2->voice();
    
    
    Animal *a = new Dog;
    delete a;

    return 0;
}


5.基于多态的依赖倒置设计原则


依赖倒置定义:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象

下面以两种不同的程序设计方法来表达设计思想


场景是这样的,母亲给孩子讲故事,只要给她一本书,她就可以照着书给孩子讲故事了。


传统过程设计:

实验代码:

#include <iostream>

using namespace std;


class Book
{
public:
    string getContents()
    {
        return "A little bear are crying";
    }
};

class News
{
public:
    string getContents()
    {
        return "Mr.Zhou were awarded with the Noble Prize";
    }
};

class Mother
{
public:
    void tellContents(Book *b)
    {
        cout<<b->getContents()<<endl;
    }

    void tellContents(News *n)
    {
        cout<<n->getContents()<<endl;
    }
};

int main()
{
    Mother m;
    Book b;
    News n;
    m.tellContents(&b);
    m.tellContents(&n);
    return 0;
}





依赖倒置设计原则:


#include <iostream>

using namespace std;

class Ireader
{
public:
    virtual string getContents() = 0;

};

class Book:public Ireader
{
public:
    virtual string getContents()
    {
        return "A little bear are crying";
    }
};

class News:public Ireader
{
public:
    virtual string getContents()
    {
        return "Mr.Zhou were awarded with the Noble Prize";
    }
};

class Mother
{
public:
    void tellContents(Ireader *i)
    {
        cout<<i->getContents()<<endl;
    }
};

int main()
{
    Mother m;
    Book b;
    News n;
    m.tellContents(&b);
    m.tellContents(&n);
    return 0;
}

电脑组装实验代码:

#include <iostream>

using namespace std;

class CPU
{
public:
    virtual void run() = 0;
};

class Mem
{
public:
    virtual void run() = 0;

};

class Disk
{
public:
    virtual void run() = 0;
};

class Intel:public CPU
{
public:
    virtual void run()
    {
        cout<<"Intel CPU"<<endl;
    }
};

class Kingston:public Mem
{
public:
    virtual void run()
    {
        cout<<"Kingston Mem"<<endl;
    }
};

class Wddisk:public Disk
{
public:
    virtual void run()
    {
        cout<<"Wddisk"<<endl;
    }
};

class Computer
{
public:
    Computer(CPU *pc,Mem *pm,Disk *pd)
        :_pc(pc),_pm(pm),_pd(pd){}
    void work()
    {
        _pc->run();
        _pm->run();
        _pd->run();
    }
    ~Computer()
    {
        delete _pc;
        delete _pm;
        delete _pd;

    }
private:
    CPU *_pc;
    Mem *_pm;
    Disk *_pd;
};

int main()
{
    Computer c(new Intel,new Kingston,new Wddisk);
    c.work();

    return 0;
}












  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值