//三大特征之一:继承
//继承的好处:减少代码重复
//语法:class 子类:public 父类
//子类 也称 派生类
//父类 也称 基类
class P{
public:
int A;
private:
int B;
};
class P1:public P
{
public:
int C;
private:
int D;
};
int main()
{
cout << "int 字节数:" << sizeof(int) << endl;//4
cout << "P 字节数:" << sizeof(P) << endl;//8
cout << "P1 字节数:(P1继承P)" << sizeof(P1) << endl;//16//父类中所有非静态成员属性都会被继承下去(包括私有)
system("pause");
return 0;
}
//子类和父类构造和析构的顺序
class Base
{
public:
Base(){
cout << "Base的构造函数\n";
}
~Base() {
cout << "Base的析构函数\n";
}
};
class Son:public Base
{
public:
Son() {
cout << "Son的构造函数\n";
}
~Son() {
cout << "Son的析构函数\n";
}
};
int main()
{
Son P;
//system("pause");
return 0;
/*Base的构造函数
Son的构造函数
Son的析构函数
Base的析构函数*/
}
//子类和父类成员函数重名时。子类会隐藏父类中所有成员函数(函数重载),静态和非静态一样
//访问子类成员:直接访问即可
//访问父类成员:加作用域即可
class Base {
public:
int m_A;//同名成员
Base(){
m_A = 100;
}
void func()//同名成员函数
{
cout << "Base成员函数调用!\n";
}
};
class Son :public Base {
public:
int m_A;
Son(){
m_A = 200;
}
void func()//同名成员函数
{
cout << "Son成员函数调用!\n";
}
};
int main()
{
Son S1;
cout << S1.m_A << endl;//200
//直接访问则访问的是子类成员,子类会隐藏父类中所有成员函数(函数重载)
cout << S1.Base::m_A << endl;//100
//子类对象加上作用域后访问父类成员(加作用域即可)
cout << endl;
S1.func();//Son成员函数调用!
//直接访问则访问的是子类成员函数
S1.Base::func();//Base成员函数调用!
//子类对象加上作用域后访问父类成员函数(加作用域即可)
cout << endl;
Base B1;
B1.func();//Base成员函数调用!
//父类成员可直接调用
return 0;
}
//语法:class 子类:继承方式 父类1,继承方式 父类2,.....
//多继承中父类成员函数重名,则要加作用域区分
class Base1 {
public:
int m_A;//重名
int m_B;
Base1() {
m_A = 100;
m_B = 200;
}
};
class Base2 {
public:
int m_A;
int m_C;
Base2() {
m_A = 100;
m_C = 0;
}
};
class Son :public Base1, public Base2//多继承
{
public:
int M_A;
Son()
{
M_A = 10;
}
};
int main()
{
Son S;
cout << S.Base1::m_A<<endl;//重名要加作用域
cout << S.Base2::m_A << endl;
cout << S.m_B << endl;//不用加作用域
cout << "Son 所占字节数:" << sizeof(S)<<endl;
system("pause");
return 0;
}
//两个类继承一个类后被另一个类继承
class Animal{
public:
int m_Age;
};
//利用虚基类解决菱形继承
//使用关键字virtual,变为虚继承,此时Animal变为虚基类
class Ship:virtual public Animal{};
class Tuo :virtual public Animal{};
class ShipTuo:public Ship, public Tuo{};
int main()
{
ShipTuo S;
//S.Ship::m_Age = 10;//需要加作用域
//S.Tuo::m_Age = 20;
//加入virtual后作用域将不再需要,m_Age共享同一个
S.m_Age = 20;
cout<<S.m_Age<<endl;
return 0;
}
多态:
多态分两大类:
静态多态:函数重载 和 运算符重载属于静态多态,复用函数名
动态多态:派生类和虚函数实现运行时多态
静态多态和动态多态区别:
静态多态的函数地址早绑定————编译阶段确定函数地址
动态多态的函数地址玩绑定————运行阶段确定函数地址
#include<iostream>
#include<string>
using namespace std;
class Animal {
public:
virtual void Speak()//父类虚函数 //vfptr virtual function pointer 虚函数指针
{
cout << "动物在说话\n";
}
};
class Cat:public Animal
{
public:
void Speak()//子类对函数重写(函数返回值、函数名、形参列表、等等都必须一致)
{
cout << "小猫在说话\n";
}
};
class Dog :public Animal
{
public:
void Speak()//子类对函数重写
{
cout << "小狗在说话\n";
}
};
动态多态满足条件
1.有继承关系
2.子类中对父类虚函数重写
子类重写虚函数,替换父类继承到子类中的虚函数,父类虚函数依然存在
多态使用
父类的指针或者引用 指向子类对象(地址晚绑定)
void doSpeak(Animal& animal)//Animal& animal=cat
{
animal.Speak();
}
int main()
{
Animal A;//父类函数依然存在
doSpeak(A); //动物在说话
Cat cat;
doSpeak(cat);//小猫在说话
Dog dog;
doSpeak(dog);//小狗在说话
system("pause");
return 0;
}
#include<iostream>
#include<string>
using namespace std;
//传统计算器
class Calculator {
public:
int m_A;
int m_B;
int getResult(string ch);
};
int Calculator::getResult(string ch)
{
if (ch == "+")
return m_A + m_B;
else if (ch == "-")
return m_A - m_B;
else if (ch == "*")
return m_A * m_B;
//继续添加除法运算,则需要修改源代码!
//引入多态
}
int main() {
Calculator c;
c.m_A = 10;
c.m_B = 10;
cout << c.m_A << "+" << c.m_B << "=" << c.getResult("+")<<endl;
cout << c.m_A << "-" << c.m_B << "=" << c.getResult("-") << endl;
cout << c.m_A << "*" << c.m_B << "=" << c.getResult("*") << endl;
}
//利用多态实现计算器
//可读性强
//组织结构清晰
//对于前期和后期扩展以及维护性高
class AbstractCaculator //实现计算器抽象类
{
public:
int m_A;
int m_B;
AbstractCaculator() {
m_A = 0;
m_B = 0;
}
AbstractCaculator(int a,int b):m_A(a),m_B(b) {}
virtual int getResult()
{
return 0;
}
};
class Add:public AbstractCaculator
{
public:
int getResult()
{
return m_A+m_B;
}
};
class Sub :public AbstractCaculator
{
public:
int getResult()
{
return m_A - m_B;
}
};
class Mul :public AbstractCaculator
{
public:
int getResult()
{
return m_A * m_B;
}
};
int main()
{
//多态的使用条件
//父类指针指向子类对象
AbstractCaculator *abc=new Add;//父类指针指向子类对象
abc->m_A = 10;
abc->m_B = 10;
cout << abc->m_A << "+" << abc->m_B << "=" << abc->getResult()<<endl;
//delete abc;
abc = new Sub;//父类指针指向子类对象
abc->m_A = 10;
abc->m_B = 10;
cout << abc->m_A << "-" << abc->m_B << "=" << abc->getResult() << endl;
delete abc;
abc = new Mul;//父类指针指向子类对象
abc->m_A = abc->m_B = 10;
cout << abc->m_A << "*" << abc->m_B << "=" << abc->getResult() << endl;
delete abc;
return 0;
}
#include<iostream>
#include<string>
using namespace std;
class Base//抽象类
{
纯虚函数
只要有一个纯虚函数,这个类成为抽象类
抽象类的特点
1、无法实例化对象
2、抽象类的子类必须(全部)重写父类中的纯虚函数,否则也是抽象类
3、可以声明一个抽象类的指针和引用。通过指针或引用,可以指向并访问派生类对象,以访问派生类的成员
public:
virtual int func() = 0;
};
class Son1:public Base
{
public:
int func()
{
cout << "Son1 func调用" << endl;
return 0;
}
};
class Son2 :public Base
{
public:
int func()
{
cout << "Son2 func调用" << endl;
return 0;
}
};
int main()
{
//Base B;抽象类无法实例化对象
Son1 S;
S.func();
//父类的指针或者引用指向子类对象(指向谁调用谁)
Base* B = new Son1;
B->func();//利用多态的技术调用
delete B;
B = new Son2;
B->func();//利用多态的技术调用
delete B;
return 0;
}
#include<iostream>
using namespace std;
class Base
{
public://纯虚函数
virtual void Boil()=0;//煮水
virtual void Brew()=0;//冲泡
virtual void PourInCup()=0;//倒入杯中
virtual void PutSomething()=0;//加入辅料
};
class Tea :public Base
{
public:
virtual void Boil()//煮水
{
cout << "水温100摄氏度!\n";
}
virtual void Brew()//冲泡
{
cout << "泡茶5分钟!\n";
}
virtual void PourInCup()//倒入杯中
{
cout << "倒入茶杯中\n";
}
virtual void PutSomething()//加入辅料
{
cout << "加入牛奶!\n";
}
};
class Coffee :public Base
{
public:
virtual void Boil()//煮水
{
cout << "水温100摄氏度!\n";
}
virtual void Brew()//冲泡
{
cout << "冲5分钟!\n";
}
virtual void PourInCup()//倒入杯中
{
cout << "倒入咖啡杯中\n";
}
virtual void PutSomething()//加入辅料
{
cout << "加入牛奶!\n";
}
};
void doWork(Base* A)
{
A->Boil();
A->Brew();
A->PourInCup();
A->PutSomething();
delete A;//防止内存泄露
}
int main()
{
doWork(new Tea);
cout << "------------------\n";
doWork(new Coffee);
return 0;
}
#include <iostream>
using namespace std;
#include <string>
class Animal
{
protected:
std::string m_name;
// We're making this constructor protected because
// we don't want people creating Animal objects directly,
// but we still want derived classes to be able to use it.
Animal(std::string name) : m_name(name){}
// To prevent slicing (covered later)
Animal(const Animal&) = default;
Animal& operator=(const Animal&) = default;
public:
string getName() const
{
return m_name;
}
virtual string speak() const//加入virtual后输出想要的结果
{
return "???";
}
};
class Cat : public Animal
{
public:
Cat(string name) : Animal(name) {}
string speak() const
{
return "Meow";
}
};
class Dog : public Animal
{
public:
Dog(string name) : Animal(name) { }
string speak() const
{
return "Woof";
}
};
int main()
{
const Cat cat("Fred");
cout << "cat is named " << cat.getName() << ", and it says " << cat.speak() << '\n';
const Dog dog("Garbo");
cout << "dog is named " << dog.getName() << ", and it says " << dog.speak() << '\n';
const Animal* pAnimal(&cat);//使用多态
cout << "pAnimal is named " << pAnimal->getName() << ", and it says " << pAnimal->speak() << '\n';
pAnimal = &dog;
cout << "pAnimal is named " << pAnimal->getName() << ", and it says " << pAnimal->speak() << '\n';
Animal* A = new Cat("Fred");
cout << "cat is named " << A->getName() << ", and it says " << A->speak() << '\n';
return 0;
}