继承
实现简单的继承关系
#include<iostream>
using namespace std;
class Person
{
public:
int _id;
};
class Student:public Person
{
public:
int _num;
};
int main()
{
Person p;
Student s;
s._id = 1;
s._num = 123456;
return 0;
}
(1)Person类中有两个成员变量_name与_id。
(2)Student类中有三个成员变量,_name、_id与_num。
(1)student占用内存大小为八个字节
三种类成员访问限定符
public(公有继承)protected(保护继承)
private(私有继承)
三种继承方式
public(公有继承)protected(保护继承)
private(私有继承)
三种继承关系下基类成员在派生类的访问关系变化
一、基类的public成员
1、在public继承方式下为public成员2、在protected继承方式下为protected成员
#include<iostream>
using namespace std;
class Person
{
public:
//构造函数进行初始化
Person()
:_age(12)
{}
void Display()
{
cout << "age:" << _age << endl;
}
private:
int _age;
};
class Student:protected Person
//此处public成员变为protected成员
{
public:
void Print()
{
Display();
}
private:
int _num;
};
int main()
{
Student s;
//s.Display()
//此处不能调用Display函数,因为其访问方式变为proteceted,但可在子类中访问
s.Print();
return 0;
}
3、在private继承方式下为private成员
#include<iostream>
using namespace std;
class Person
{
public:
Person()
:_age(12)
{}
void Display()
{
cout << "age:" << _age << endl;
}
private:
int _age;
};
class Student:private Person
//在类外不可被访问,但在子类中可以被访问
{
public:
void Print()
{
Display();
}
private:
int _num;
};
int main()
{
Student s;
//s.Display();//此处不可调用Display()函数
s.Print();
return 0;
}
二、基类的protected成员
1、在public继承方式下为protected成员//main函数中不可调用Display函数,但是可以调用Print函数,因此可调用Stuudent类中Print函数间接调用Display函数
2、在protected继承方式下为protected成员
3、在private继承方式下为private成员
三、基类的private成员
1、在public继承方式下为private成员//此程序编译不通过
#include<iostream>
using namespace std;
class Person
{
public:
Person()
:_age(12)
{}
private:
int _age;
void Display()
{
cout << "age:" << _age << endl;
}
};
class Student:public Person
{
public:
void Print()
{
Display();
//此时Display为private函数,在子函数中也不可调用
}
private:
int _num;
};
int main()
{
Student s;
//s.Display();
s.Print();
return 0;
}
2、在protected继承方式下为protected成员
//同上
3、在private继承方式下为private成员
//同上
小结
1、public继承方式下基类成员的访问方式不变2、protected继承方式下,public\protected成员均为protected访问方式,private成员仍为private
3、private继承方式下基类成员的访问方式均为private
总结
1、private和protected访问限定符的区别:父类中的private成员在限制了类外访问的同时也限制了子类的访问,即只允许在父类中访问;而父类中的protected成员可在子类中被访问的同时限制了类外的访问。2、public继承是一个接口继承,保持is-a原则,每个父类可用的成员子类也可用,因为每个子类对象也都是一个父类对象。
3、不管是哪种方式,在派生类内部都可以访问基类中的public成员和protected成员,但是基类中的私有成员在派生类中不可见(不能访问)。
4、使用关键词class时,默认的继承方式是private,使用关键词struct是,默认的继承方式是public。
5,继承是一种复用手段
继承与转换--赋值兼容规则
前提:public继承
子类->父类
1、子类可以赋值给父类对象(切割/切片)将子类s中与t有关的对象值赋给父类对象t
2、子类指针赋值给父类指针
父类指针指向子类中父类的部分
3、子类指针赋值给父类引用
r变成子类中父类部分的别名
#include<iostream>
using namespace std;
class Person
{
public:
Person(const string name = "")
:_name(name)
{}
protected:
string _name;
};
class Student : public Person
{
public:
Student(const string name, int num)
:Person(name)
, _num(num)
{}
void Display()
{
cout << _num << endl;
}
protected:
int _num;
};
int main()
{
Person p;
Student s("张三", 123);
s.Display();
p = s;//子类对象赋值给父类对象
Person *p1 = &s;//子类对象传给父类指针
Person &p2 = s;//子类对象传给父类引用
return 0;
}
#### 父类->子类
1、父类对象赋值给子类对象绝对不可以
2、父类指针赋值给子类指针
进行类型强转后可以,但是,在子类指针s访问子类成员_num是会产生越界,从而程序终止
3、父类指针赋值给子类引用
进行类型强转后可以,但是,在子类指针s访问子类成员_num是会产生越界,从而程序终止
#include<iostream>
using namespace std;
class Person
{
public:
Person(const string name = "")
:_name(name)
{}
protected:
string _name;
};
class Student : public Person
{
public:
Student(const string name, int num)
:Person(name)
, _num(num)
{}
void Display()
{
cout << _num << endl;
}
protected:
int _num;
};
int main()
{
Person p;
Student s("张三", 123);
s.Display();
Student s1 = p;//父类对象赋值给子类对象
Student *s2 = (Student*)&p;//父类对象赋给子类指针
Student &s3 = (Student&)p;//父类对象赋给子类引用
return 0;
}