首先说一个基本例子:
//人类
class Human{
public:
void say(){
cout << "说话" << endl;
}
protected:
char* name;
int age;
};
//男人
class Man : public Human{
public:
//泡妞
void chasing(){
cout << "泡妞" << endl;
}
private:
//兄弟
char* brother;
};
void work(Human& h){
h.say();
}
void main(){
Man m1;
m1.say();
//1.父类类型的引用或指针
Human* h_p = &m1;
h_p->say();
Human &h1 = m1;
h1.say();
//子类对象初始化父类类型的对象
Human h2 = m1;
system("pause");
}
可以看出,这里的多态,和JAVA也几乎一样,左边是父类,右边是子类,父类的引用指向子类的对象。
再说下 构造函数与析构函数调用的顺序,下面的例子中,在初始化子类时,也会给父类赋值
class Human{
public:
Human(char* name, int age){
this->name = name;
this->age = age;
cout << "Human 构造函数" << endl;
}
~Human(){
cout << "Human 析构函数" << endl;
}
void say(){
cout << "说话" << endl;
}
protected:
char* name;
int age;
};
//男人
class Man : public Human{
public:
//给父类构造函数传参,同时给属性对象赋值
Man(char *brother, char *s_name,int s_age) : Human(s_name, s_age){
this->brother = brother;
cout << "Man 构造函数" << endl;
}
~Man(){
cout << "Man 析构函数" << endl;
}
//泡妞
void chasing(){
cout << "泡妞" << endl;
}
private:
//兄弟
char* brother;
};
void func(){
//父类构造函数先调用
//子类的析构函数先调用
Man m1("danny", "jack", 18);
}
void main(){
func();
system("pause");
}
子类对象调用父类的成员
class Human{
public:
Human(char* name, int age){
this->name = name;
this->age = age;
cout << "Human 构造函数" << endl;
}
~Human(){
cout << "Human 析构函数" << endl;
}
void say(){
cout << "说话" << endl;
}
public:
char* name;
int age;
};
//男人
class Man : public Human{
public:
//给父类构造函数传参,同时给属性对象赋值
Man(char *brother, char *s_name, int s_age) : Human(s_name, s_age){
this->brother = brother;
cout << "Man 构造函数" << endl;
}
~Man(){
cout << "Man 析构函数" << endl;
}
//泡妞
void chasing(){
cout << "泡妞" << endl;
}
void say(){
cout << "男人喜欢装逼" << endl;
}
private:
//兄弟
char* brother;
};
void main(){
//是覆盖,并非动态
Man m1("alan","john",18);
m1.say();
m1.Human::say();
m1.Human::age = 10;
system("pause");
}
举个多继承的例子
class Person{
};
//公民
class Citizen{
};
//学生,既是人,又是公民
class Student : public Person, public Citizen{
};
可以看到,继承的时候,其实是有 访问修饰符 的,这里举一个表
//继承的访问修饰
//基类中 继承方式 子类中
//public & public继承 = > public
//public & protected继承 = > protected
//public & private继承 = > private
//
//protected & public继承 = > protected
//protected & protected继承 = > protected
//protected & private继承 = > private
//
//private & public继承 = > 子类无权访问
//private & protected继承 = > 子类无权访问
//private & private继承 = > 子类无权访问
一句话,以最低权限为上限,基类private,子类无权限,就对了
//继承的二义性
//虚继承,不同路径继承来的同名成员只有一份拷贝,解决不明确的问题
class A {
public:
char* name;
};
class A1 : virtual public A {
};
class A2 : virtual public A {
};
class B : public A1, public A2 {
};
void main() {
B b;
b.name = "jason";
//指定父类显示调用
//b.A1::name = "jason";
//b.A2::name = "jason";
system("pause");
}
由于用了A1,A2都用了虚继承自A,故这里就只有一份A的类在内存中,也就是说,b.A1::name 与 b.A2::name 都是同一个东西!! 这里就直接b.name就行了。
//纯虚函数(抽象类)
//1.当一个类具有一个纯虚函数,这个类就是抽象类
//2.抽象类不能实例化对象
//3.子类继承抽象类,必须要实现纯虚函数,如果没有,子类也是抽象类
//抽象类的作用:为了继承约束,根本不知道未来的实现
如下例子:
class Shape{
public:
//纯虚函数
virtual void sayArea() = 0;
void print(){
cout << "hi" << endl;
}
};
//圆
class Circle : public Shape{
public:
Circle(int r){
this->r = r;
}
void sayArea(){
cout << "圆的面积:" << (3.14 * r * r) << endl;
}
private:
int r;
};
void main(){
//Shape s;
Circle c(10);
system("pause");
}
所以,申明了纯虚函数,就是个抽象类,继承这个抽象类,就要实现其方法,这点跟JAVA也差不多。不实现方法的话,依然属于抽象类,不能有实例。