c++抽象类练习

Animal.h

#pragma once

#define _CRT_SECURE_NO_WARNINGS

//抽象层
#include <iostream>
#include <string>

using namespace std;

class Animal
{
public:
    Animal(string kind, string color);//这儿写有参构造不是无用的,是为了使子类通过初始化列表直接对父类对象进行赋值构造,不需要再返回父类中私有成员变量的引用
    virtual void voice() = 0;
    string getKind();
    string getColor();
    virtual ~Animal();
private:
    string kind;
    string color;
};

class Dog :public Animal
{
public:
    Dog(int age, string kind, string color);//函数初始化列表如果只是声明时,是不需要写出来的,只需要在定义时指定就可以了
    virtual void voice();
private:
    int age;
};

class Cat :public Animal
{

public:
    Cat(int weight, string kind, string color);
    virtual void voice();
private:
    int weight;
};

//架构函数,也属于抽象层

void setAnimalVoice(Animal *a);


Computer.h

#pragma once
#define _CRT_SECURE_NO_WARNINGS

#include <iostream>

using namespace std;

class Cpu
{
public:
    virtual void caculate() = 0;//这是纯虚函数,不需要定义的,只需要在类里重写就可以,纯虚函数和虚函数时一样的,都可以触发多态
    virtual ~Cpu();//有类继承,则父类一定要写成虚析构函数
};

class Card
{
public:
    virtual void display() = 0;//这是纯虚函数,不需要定义的,只需要在类里重写就可以
    virtual ~Card();//有类继承,则父类一定要写成虚析构函数
};

class Memory
{
public:
    virtual void storage() = 0;//这是纯虚函数,不需要定义的,只需要在类里重写就可以
    virtual ~Memory();//有类继承,则父类一定要写成虚析构函数
};

//三个等级直接使用指针,不使用继承
class Computer//没有继承的则不需要写虚析构函数,因为没有继承就没有多态,没有多态就不需要区分调用父类析构还是子类析构
{
public:
    //这是直接调用父类指针,可以指向子类,发生多态
    Computer(Cpu *cpu, Card *card, Memory *memory);
    void print();
private:
    Cpu * cpu;
    Card *card;
    Memory *memory;
};

class IntelCpu :public Cpu
{
public:
    virtual void caculate();
};

class IntelCard :public Card
{
public:
    virtual void display();
};

class IntelMemory :public Memory
{
public:
    virtual void storage();
};

class NvidiaCard :public Card
{
public:
    virtual void display();
};

class KingstonMemory :public Memory
{
public:
    virtual void storage();

};


Animal.cpp

#include "Animal.h"

//实现层
Animal::Animal(string kind, string color)
{
    this->kind = kind;
    this->color = color;
}
string Animal::getKind()
{
    return kind;
}
string Animal::getColor()
{
    return color;
}
Animal::~Animal()//这为虚析构函数的定义,~Animal一定要带上~才表示为虚析构函数名,这个虚析构函数的名称为~Animal这个整体
{
    //虚析构函数如果声明了就必须定义,其他类的成员函数也是一样
    cout << "~Animal......" << endl;
}


Dog::Dog(int age, string kind, string color) :Animal(kind, color)//函数初始化列表不需要在另一个构造函数前加作用域,只要在实现的函数名前加作用域就可以了
{
    //这里只用对子类额外的对象赋值就可以了,父类中的基类变量直接通过初始化列表进行赋值构造了,要明确父类中的变量域虽然不同的子类都有,但这些变量域的值却是各不相同的
    this->age = age;
}
void Dog::voice()//virtual Dog::voice在类外部实现方法的这种写法是错误的,不需要加virtual,加了反而报错
{
    cout << this->getColor() << " " << this->getKind() << ":" << "wangwangwang" << endl;
}

Cat::Cat(int weight, string kind, string color) :Animal(kind, color)
{
    this->weight = weight;
}
void Cat::voice()
{
    cout << this->getColor() << " " << this->getKind() << ":" << "miaomiaomiao" << endl;
}

void setAnimalVoice(Animal *a)
{
    a->voice();

}



Computer.h


#include "Computer.h"

Cpu::~Cpu()
{
    cout << "~cpu......" << endl;
}

Card::~Card()
{
    cout << "~Card......" << endl;
}

Memory::~Memory()
{
    cout << "~Memory......" << endl;
}

Computer::Computer(Cpu *cpu, Card *card, Memory *memory)
{
    this->cpu = cpu;
    this->card = card;
    this->memory = memory;
}

void Computer::print()
{
    cpu->caculate();  
    card->display();
    memory->storage();
}

void IntelCpu::caculate()
{
    cout << "IntelCpu caculate" << endl;
}

void IntelCard::display()
{
    cout << "IntelCard display" << endl;
}

void IntelMemory::storage()
{
    cout << "IntelMemory storage" << endl;
}

void NvidiaCard::display()
{
    cout << "NvidiaCard display" << endl;
}

void KingstonMemory::storage()
{
    cout << "KingstonMemory storage" << endl;
}



c++抽象类练习.cpp


#include "Animal.h"
#include "Computer.h"

//这是抽象类
class A
{
public:
    virtual void print() = 0;
    virtual ~A()//就算是抽象类,这儿也应该写成虚析构函数,因为当需要使用多态时,在堆里开辟空间,析构父类指针时,父类不写成虚析构函数,就不会发生虚构多态,那么只会调用父类的析构函数,不会调用子类的析构函数
    {
        cout << "~A......" << endl;
    }
};

class C :public A
{
public:
    virtual void print()
    {

    }
    ~C()
    {
        cout << "~C()......" << endl;
    }
};

//业务逻辑层
int main()
{
    Animal *a1 = new Dog(3, "dog", "yellow");
    Animal *a2 = new Cat(20, "cat", "black");
    //方法1:
    a1->voice();
    a2->voice();

    //方法2:
    setAnimalVoice(a1);
    setAnimalVoice(a2);
    //下面两段代码的写法也是可以的,但要注意创建的是匿名对象了,把匿名对象赋值给了函数的参数,此时释放开辟出来的空间需要在函数里释放,在main方法里是释放不了的
    //setAnimalVoice(new Dog);
    //setAnimalVoice(new Cat);
    //方法2的两种用法第二种会有风险,所以选取哪种用法看你自己选择

    delete a1;
    delete a2;

    cout << "------------------------------------" << endl;

    A *test1 = new C();
    delete test1;

    cout << "-----------------------------------------" << endl;

    Cpu *cp1 = new IntelCpu();
    Card *ca1 = new IntelCard();
    Memory *me1 = new IntelMemory();
    Card *ca2 = new NvidiaCard();
    Memory *me2 = new KingstonMemory();

    Computer *c1 = new Computer(cp1, ca1, me1);
    Computer *c2 = new Computer(cp1, ca2, me2);
    
    c1->print();
    c2->print();

    //每个new出来的对象都需要delete,不然不会触发析构函数
    delete cp1;
    delete ca1;
    delete ca2;
    delete me1;
    delete me2;

    //这析构的只是c2指向的对象,对于传进来的指针指向的对象并不会被析构
    delete c2;
    delete c1;
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值