一、继承的概念
继承(Inheritance)可以理解为一个类从另一个类获取成员变量和成员函数的过程。例如类 B 继承于类 A,那么 B 就拥有 A 的成员变量和成员函数。被继承的类称为父类或基类,继承的类称为子类或派生类。
二、继承权限和继承方式
1、语法
在子类后添加 :加权限+类名
派生类属于基类的外部,不能直接访问private的变量。
需要将private修改为protected:保护权限,用于衍生类的继承。
#include <iostream>
#include <cstring>
using namespace std;
class Person //父类或者基类
{
//private:
protected: //保护权限:类的内部可以访问,类的派生类可以访问。类的外部不能访问。
char name[32];
int age;
public:
Person()
{
strcpy(name,"aaa");
age = 20;
}
};
class Student : public Person //子类或者派生类 public 继承的权限
{
private:
int id;
public:
Student(int id)
{
this->id = id;
}
void show()
{
cout << name << " " << age << " " << id <<endl;
//cout << id << endl;
}
};
int main()
{
Student s1(1);
s1.show();
return 0;
}
2、继承的权限
1、继承的变量会根据继承的权限,来变更变量的权限,限制了成员在派生类中的最高权限
(例如原来是公有权限,继承权限是私有,那么在子类会变成私有变量,权限的保护程度只能提高,不能降低,例如保护变量,不会降低成为公有变量)
2、私有变量可以继承,但是不能被继承访问,因为私有变量是类私有的,是不能被外部类访问继承的。
#include <iostream>
using namespace std;
class TestA
{
private: //私有变量不能被继承访问
int a; //只能在类的内部访问
protected:
int b;
public:
int c;
};
//私有继承
class TestB : private TestA
{
//原本b是protected权限,继承以后降级为private 共有和保护都变成了私有
//相当于:private:int b
public:
void test()
{
//a++; //在testA中 A是私有成员变量,不能访问
b++;
c++;
}
};
//保护继承
class TestC : protected TestA
{
//c原来是共有继承,被保护权限后,共有变量变成保护变量
public:
void test()
{
//a++;
b++;
c++;
}
};
class TestD : public TestA
{
public:
void test()
{
//a++
b++;
c++;
}
};
//限制了成员在派生类中的最高权限
int main()
{
TestB tb;
//tb.b; 不能访问了
//tb.c;
TestD td;
//td.b; b继承下来还是保护权限,不能在外部访问。
td.c;
return 0;
}
三、继承中的构造和析构
1、继承中的对象模型
①继承的变量占多少字节在子类就占多少字节
②子类继承下来的基类变量放在前面,再存放子类成员
#include <iostream>
using namespace std;
class Person
{
public:
int age;
};
class Student :public Person //继承下来的放在前面
{
public:
int id;
};
int main()
{
Student s;
cout << sizeof(s) << endl;
cout << &s << endl;
cout << &s.age << endl;
cout << &s.id << endl;
return 0;
}
2、继承中的构造析构调用原则
1、创建派生类对象,会调用基类构造函数
2、当基类没有提供无参构造函数时,派生类需要通过对象初始化链表类传参
3、析构的顺序和构造相反,先入后出
4、构造顺序:先构造父类,再构造成员,最后构造自己。
#include <iostream>
#include <cstring>
using namespace std;
class Person //父类或者基类
{
//private:
protected: //保护权限:类的内部可以访问,类的派生类可以访问。类的外部不能访问。
char name[32];
int age;
public:
/*Person()
{
cout << "person的构造函数" << endl;
strcpy(name,"aaa");
age = 20;
}*/
Person(const char *n,int a)
{
cout << "Person有参构造函数" << endl;
strcpy(name,n);
age = a;
}
~Person()
{
cout << "Person 析构函数"<< endl;
}
};
class Date
{
protected :
int year;
int mouth;
int day;
public :
Date(int y,int m,int d)
{
cout << "Date有参构造函数" << endl;
year = y;
mouth = m;
day = d;
}
~Date()
{
cout << "Date析构函数" << endl;
}
};
class Student : public Person //子类或者派生类 public 继承的权限
{
//先构造父类,再构造成员,最后构造自己。
private:
Date birth;
int id;
public:
Student(int id) : Person("aaa",23),birth(1,1,1) //当基类没有提供无参构造函数时,派生类需要通过对象初始化链表类传参
{
cout << "Student构造函数" << endl;
this->id = id;
}
void show()
{
cout << name << " " << age << " " << id <<endl;
//cout << id << endl;
}
~Student()
{
cout << "Student 析构函数" << endl;
}
};
int main()
{
Student s1(1); //创建派生类对象,会调用基类构造函数,来初始化继承来的成员
s1.show();
return 0; //析构的顺序和构造相反,先入后出
}
3、继承中的同名成员变量处理方法
1、同名,不会被覆盖
2、如果是同名,默认调用派生类函数(在派生类被隐藏)
3、调用基类函数,可以添加作用域。
#include <iostream>
using namespace std;
class TestA
{
private:
int a;
public:
void show()
{
cout << "this is TestA" << endl;
}
};
class TestB : public TestA
{
private:
int a;
public:
void show()
{
cout << "this is TestB" << endl;
}
};
int main()
{
TestB tb;
cout << sizeof(TestB) << endl; //没有被覆盖
tb.show(); //如果是同名,默认调用派生类函数
tb.TestA::show();
return 0;
}
4、派生类中的static关键字
派生类,基类共享同一个静态成员变量
#include <iostream>
using namespace std;
class Person
{
public:
static int count;
Person()
{
count++;
}
};
int Person::count = 0;
class Student : public Person
{
};
int main()
{
Student s1;
Student s2;
Student s3;
Person p1;
Person p2;
cout << Person::count << endl; //派生类,基类共享同一个静态成员变量
cout << Student::count << endl;
cout << s1.count << endl;
return 0;
}