引入继承
为什么需要继承?
C++中代码的可重用性通过继承机制来实现。
简单举例
代码演示:
#include <iostream>
using namespace std;
class Student
{
public:
void study(string course)
{
cout << " i am a student , i am learning " << course << endl;
}
void eat(string food)
{
cout << " i am eating " << food << endl;
}
};
class Teachers
{
public:
void tech(string course)
{
cout << " i am teacher , i am teaching " << course << endl;
}
void eat(string food)
{
cout << " i am eating " << food << endl;
}
};
int main()
{
return 0;
}
上面代码中,Teachers类 和 Student 类 具有相同的方法 eat ,那么就可以将 eat 方法进行抽象。
提取 Teachers类 和 Student 类 的公共方法到 Human类 ,让Teachers类 和 Student 类 继承 Human类 实现代码可重用。 代码演示:
#include <iostream>
using namespace std;
class Human
{
public:
void eat(string food)
{
cout << " i am eating " << food << endl;
}
};
class Student :public Human
{
public:
void study(string course)
{
cout << " i am a student , i am learning " << course << endl;
}
};
class Teacher :public Human
{
public:
void tech(string course)
{
cout << " i am teacher , i am teaching " << course << endl;
}
};
int main()
{
Student s;
s.study("C++");
s.eat("裤带面");
Teacher t;
t.tech("python");
t.eat("油泼辣子酸汤面");
return 0;
}
运行结果: 结论: 继承是一种设计的结果,通常是发生于一套类库中的,设计代码重用的方式。 这种关系是一种设计而为之,不是想继承,就可随便继承的。
继承
定义
类的继承,是新的类从已有类那里得到已有的特性。 从已有类产生新类的过程就是类的派生。
子类 --> 继承 --> 父类 [继承关系]
基类 --> 派生 --> 派生类 [派生关系]
定性 is-a 而不是 has-a
is-a
is-a 是一种属于关系。
例如: 狗属于一种动物。 可以设计一个 Animal 类,Dog 类作为Animal 类(基类)的派生类;
车属于一种交通工具,在面向对象中表现为一种继承关系。 设计一个 Vehicle 类,Car 类作为 Vehicle 类(基类)的派生类。
has-a
has-a 是一种包含、组合关系。 例如: 车包含方向盘、轮胎、发动机。 但不能说方向盘/轮胎/发动机是一种车。 正确的应该说车聚合(包含)了方向盘、轮胎、发动机。
狗包含腿、尾巴。 但不能说腿、尾巴是一种狗。
如果 A is a B,则 B 是 A 的基类,A 是 B 的派生类。为继承关系。 如果 A 包含 B,则 B 是 A 的组成部分,为聚合关系,可以由组成部分聚合成为一个类。
语法
class 派生类名:[继承方式] 基类名
{
派生类成员声明;
};
默认的继承方式是 private 私有继承。
一个派生类可以同时有多个基类,这种情况称为多重继承。 派生类只有一个基类,称为单继承。
继承方式
继承方式影响了什么?
继承方式规定了子类如何访问从基类继承的成员。 继承方式有 public, private, protected。 继承方式不影响派生类的访问权限,影响了从基类继承而来的成员的访问权限,包括派生类内的访问权限和派生类对象的访问权限。 代码演示:
#include <iostream>
using namespace std;
class Base
{
public:
int pub;
protected:
int pro;
private:
int pri;
};
class Drive :public Base
{
public:
void func()
{
pub = 10;
pro = 100;
pri = 1000;
}
public:
int a;
protected:
int b;
private:
int c;
};
int main()
{
Base b;
b.pub = 10;
b.pro = 100;
b.pri = 1000;
return 0;
}
编译器报错:
公有继承 public
基类的公有成员和保护成员在派生类中保持原有访问属性,其私有成员仍为基类的私有成员。
私有继承 private
基类的公有成员和保护成员在派生类中成了私有成员,其私有成员仍为基类的私有成员。
保护继承 protected
基类的公有成员和保护成员在派生类中成了保护成员,其私有成员仍为基类的私有成员。
继承方式结论
派生类的组成
组成图示
派生类中的成员,包含两大部分,一类是从基类继承过来的,一类是自己增加的成员。 从基类继承过过来的表现其共性,而新增的成员体现了其个性。
说明
全盘接收,除了构造器与析构器。 基类有可能会造成派生类的成员冗余,所以说基类是需设计的。 派生类有了自己的个性,使派生类有了意义。
sizeof(父类 / 子类)
代码演示:
#include <iostream>
using namespace std;
class Base
{
public:
int pub;
protected:
int pro;
private:
int pri;
};
class Drive :public Base
{
public:
void func()
{
pub = 10;
pro = 100;
}
public:
int a;
protected:
int b;
private:
int c;
};
int main()
{
cout << "sizeof(Base) = " << sizeof(Base) << endl;
cout << "sizeof(Drive) = " << sizeof(Drive) << endl;
return 0;
}
运行结果:
继承的内存模型
#include <iostream>
#include <typeinfo>
using namespace std;
class A
{
public:
A()
{
cout << this << endl;
cout << typeid(this).name() << endl;
}
int a;
};
class B :public A
{
public:
B()
{
cout << this << endl;
cout << typeid(this).name() << endl;
}
int b;
};
class C :public B
{
public:
C()
{
cout << this << endl;
cout << typeid(this).name() << endl;
}
void func()
{
cout << &a << endl;
cout << &b << endl;
cout << &c << endl;
}
int c;
};
int main()
{
C c;
cout << "&c " << &c << endl;
cout << "*************" << endl;
c.func();
return 0;
}
运行结果: 类A,B,C 和对象 c 地址相同。 类A,B,C 的类型不同,分别为 class A*, class B*, class C* 。 从结果得出:子类生成对象,先构造父类,后构造子类。
|