网站建设公司推广网站品牌运营,聊城seo培训,唐山哪个公司做网站,网页制作什么主题好继承 1. 继承的概念和定义1.1 继承的概念1.2 继承的定义1.2.1 继承的格式1.2.2 继承方式 2. 基类和派生类对象的赋值转换3.继承中的作用域4. 继承中的默认成员函数5. 继承和友元6. 继承和静态成员 1. 继承的概念和定义
1.1 继承的概念 继承是面向对象编程中的一个重要概念它允许一个类称为子类/派生类继承另一个类称为父类/基类的属性和方法。子类可以重用父类的代码并且可以添加自己的新属性和方法或者重写父类的方法以满足自己的特定需求。 继承呈现了面向对象程序设计的层次结构体现了由简单到复杂的认知过程。 1.2 继承的定义
1.2.1 继承的格式 class 派生类 : 继承方式 基类 class Person
{
protected:string _name;int _age;
};class Student : public Person
{
protected:int _stuid;
};1.2.2 继承方式
继承方式的关键字和访问修饰权限符是一样的有三种public、protected、private。相信大家都很熟悉。那这三种继承方式会有什么不同呢情况有很多但大家只要记住一句话取权限小的那个按照权限排序是public protected private。比如为public继承方式我们用pubilc和基类的成员变量、成员函数的访问修饰权限符作比较取小的那个作为派生类继承过来的该成员变量或成员函数的访问权限符号。 总结
基类private成员在派生类中无论以什么方式继承都是不可见的。这里的不可见是指基类的私有成员还是被继承到了派生类对象中但是语法上限制派生类对象不管在类里面还是类外面都不能去访问它。在继承之前是没有protected这个关键字出现的。基类private成员在派生类中是不能被访问如果基类成员不想在类外直接被访问但需要在派生类中能访问就定义为protected。使用关键字class时默认的继承方式是private使用struct时默认的继承方式是public不过最好显示的写出继承方式。实际运用中基本使用public继承方式。
2. 基类和派生类对象的赋值转换
先说几个结论
派生类对象可以赋值给基类的对象、基类的指针、基类的引用。这时候会发生对象切片object slicing。这意味着只有基类部分的成员变量和方法会被复制到基类对象中而派生类特有的成员变量和方法将被丢失。基类的对象不能赋值给派生类。类的指针或者引用可以通过强制类型转换赋值给派生类的指针或者引用。但是必须是基类的指针是指向派生类对象时才是安全的。这里基类如果是多态类型可以使用RTTI(RunTime Type Information)的dynamic_cast 来进行识别后进行安全转换。
代码演示
class Person
{
protected:string _name 张三;int _age 18;
};
class Student : public Person
{
protected:int _stuid 10086;
};
int main()
{Student s;Person p;p s;Person* p1 new Student;Person p2 s;return 0;
}3.继承中的作用域
我们思考一个问题如果父类和子类的成员对象名一样会发生什么
class A
{protected:int num 10;
};
class B : public A
{
public:void fun(){cout num endl;}
protected:int num 20;
};
int main()
{B b;b.fun();
}从结果可以看出我们打印出来的是B中的num那么A中的num去哪了是被重新赋值了吗答案是被隐藏了也叫重定向它在A的作用域中可以通过来访问。
class A
{protected:int num 10;
};
class B : public A
{
public:void fun(){cout B的num: num endl;cout A的num: A::num endl;}
protected:int num 20;
};
int main()
{B b;b.fun();
}函数也是同理只需要函数名称相同基类的函数就会被隐藏起来。
class A
{
public:int fun(int a, int b){cout 我是A的fun endl;return a b;}
protected:int num 10;
};
class B : public A
{
public:void fun(){cout 我是B的fun endl;}
protected:int num 20;
};
int main()
{B b;b.fun();
}总结 在继承体系中基类和派生类都有独立的作用域。子类和父类中有同名成员子类成员将屏蔽父类对同名成员的直接访问这种情况叫隐藏 也叫重定义。在子类成员函数中可以使用 基类::基类成员 显示访问需要注意的是如果是成员函数的隐藏只需要函数名相同就构成隐藏。注意在实际中在继承体系里面最好不要定义同名的成员 4. 继承中的默认成员函数
我们之前将如果我们不写编译器会默认生成6个成员函数。我们这里讨论前4个函数在继承中的行为。 派生类的构造函数必须调用基类的构造函数来初始化基类那部分的成员变量。如果基类没有默认构造那我们必须在派生类的初始化列表显示调用构造函数。必须先构造父类再构造子类派生类的拷贝构造函数必须调用基类的拷贝构造函数来完成基类的初始化。派生类的赋值必须要调用子类的赋值必须先析构派生类然后再析构基类因为如果先析构基类会造成派生类如果使用基类的成员会造成野指针问题。注虽然派生类的析构函数名和基类的析构函数名不同但由于后面的多态重写部分析构函数名会被编译器处理destrutor()。所以基类析构函数不加virtual的情况下派生类析构函数和父类析构函数构成隐藏关系。派生类的析构函数不用显示调用基类的析构函数编译器会在派生类析构以后再自动调用基类的析构函数保证了第4点。 class Person
{
public:Person(string name,int age):_name(name),_age(age){cout Person(string name,int age) endl;}Person(const Person l){_name l._name;cout Person(const Person l) endl;}Person operator(const Person l){cout Person operator(const Person l) endl;if (this ! l){_name l._name;}return *this;}~Person(){cout ~Person() endl;}
protected:string _name;int _age;
};class Student : public Person
{
public:Student(string name, int age, int stid):Person(name, age), _stid(stid){cout Student(string name, int age, int stid) endl;}Student(const Student s):Person(s){cout Student(const Student s) endl;_stid s._stid;}Student operator(const Student s){cout Student operator(const Student s) endl;Person::operator(s);if (this ! s){_stid s._stid;}}~Student(){cout ~Student() endl;}
protected:int _stid;
};int main()
{Student s(张三,20,10086);Student s1(s);Student s2 s1;return 0;
}5. 继承和友元 爸爸的朋友并不是你的朋友所以友元关系不能继承。故友元函数不能访问子类的私有和保护成员。 6. 继承和静态成员 基类定义了static静态成员则整个继承体系里面只有一个这样的成员。无论派生出多少个子 类都只有一个static成员实例。