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