在。在本教程中,我们将学习以下主题:
- 介绍
- 由不同的访问说明符得出:
- C ++基类指针和派生类指针。
- 虚拟基础类
- 继承中的构造方法和析构方法调用
- 多重继承中的构造方法和析构方法调用
- 指针与继承
1.简介
继承是在现有类的帮助下创建新类的一种方法。
现有类称为基类[父类,超类],新类称为继承类[子类,子类,派生类]。
新的派生类可以拥有它’自己的数据成员和成员函数以及基类的一些数据成员和成员函数。
句法:
class <DerivedCalssName> : <accessSpecifier> <BaseClassName>
派生类的大小将始终等于或大于基类。
派生类只能访问基类的公共成员或受保护成员。私有数据成员将被继承,但不能使用。
例:
#include<iostream> using namespace std; class A { int a; 上市: void display() { cout<<"This is display from A class"<<endl; } }; class B :public A { int b; 上市: void display() { cout<<"This is display from B class"<<endl; } }; int main() { A a1; a1.display(); // "A" class display() B b1; b1.display(); // "B" class display function. cout<<"Size of object of A class " << sizeof(a1)<<endl; cout<<"Size of object of B class " << sizeof(b1)<<endl; }
输出:
This is display from A class This is display from B class Size of object of A class 4 Size of object of B class 8
2.由不同的访问说明得出:
可以使用3种类型的访问说明符。
- 上市
- 私人的
- 受保护的
使用公共访问说明符得出:
- 基类的公共成员将是派生类的公共成员。
- 基类的受保护成员将是派生类的受保护成员。
- 基类的私有成员不可访问派生类。因此不被继承。
例:
class DerivedClass : 上市 BaseClass
使用受保护的访问说明符得出:
- 基类的公共成员将是派生类的受保护成员。
- 基类的受保护成员将是派生类的受保护成员。
- 基类的私有成员不可访问派生类。因此不被继承。
例:
class DerivedClass : 受保护的 BaseClass
使用私有访问说明符派生:
- 基类的公共成员将是派生类的私有成员。
- 受保护的基类成员将是派生类的私有成员。
- 基类的私有成员不可访问派生类。因此不被继承。
例:
class DerivedClass : 私人的 BaseClass
3。
基类指针:
基类指针可以存储派生类的地址。这是有效的,因为派生类对象将具有基类的成员。
因此,当基类的指针可以访问它时’的成员。但是,在这种情况下,指针将无法访问派生的类成员。由于基类指针将不具有有关派生类成员的任何信息。
例:
#include<iostream> using namespace std; class Base { 上市: int a; void display() { cout<<"This is base class show()"<<endl; } }; class Derived : 上市 Base { 上市: int b; void display() { cout<<"This is derived class show()"<<endl; } }; int main() { Base *b1; Derived der; b1 = &der; b1->display(); b1->a; // b1->b; // error member b is not found in Base class return 0; }
输出:
This is base class show()
派生类指针:
派生类指针不能保存基类对象的地址。因为,派生类指针应该访问基类和派生类的所有成员。
通过使派生类指针保存基类的地址,它无法访问派生类成员。因此,编译器将引发错误。
例:
与上面的程序相同,我们对main()进行了少许更改
int main() { Base b1; Derived *der; der= &b1; //error }
4.虚拟基础类
在进入“虚拟基类”之前,我们将了解为什么需要这样做。我们将在下一章介绍继承的类型,但是现在,有了多路径继承的概念。
从上面的示例中,我们可以看到,Class B继承了Class A,Class C也继承了ClassA。ClassD同时继承了B和C。因此,此处Class A将被继承两次。因此,当我们尝试访问A类变量时,会出现以下错误:
error: non-static member 'a' found in multiple base-class subobjects of type 'A': class D -> class B -> class A class D -> class C -> class A cout<<"The value of a "<<a; ^
注意:通过不明确的名称查找找到成员
int a; ^
产生1个错误。
为了使编译器仅继承一次,无论何时继承基类,我们都应将其设为``虚拟''。通过将一个类虚拟化,编译器将采取必要的步骤来确保所有类仅被继承一次。
“ virtual”是用于声明虚拟类的关键字。
/* * File : virtual_base_class.cpp * Author : [email protected] * Copyright: @ 前开发者教程.com */ #include<iostream> using namespace std; class A { 上市: int a; }; class B: virtual 上市 A { 上市: int b; }; class C: virtual 上市 A { 上市: int c; }; class D: 上市 B, C { 上市: int d; void display() { cout<<"The value of a "<<a; } }; int main() { D d1; }
当您编译以上代码时,将不会显示任何错误。
5.继承中的构造函数和析构函数调用
在继承期间,始终将调用基类构造函数,而以后将调用派生类构造函数。
同样,析构函数调用将相反。首先将调用派生类析构函数,然后将调用基类析构函数。
例:
/* * File : constructor_destructor_in_inheritance.cpp * Author : [email protected] * Copyright: @ 前开发者教程.com */ #include<iostream> using namespace std; class A { 上市: A() { cout<<"Constructor of A"<<endl; } ~A() { cout<<"Destructor of A"<<endl; } }; class B: 上市 A { 上市: B() { cout<<"Constructor of B"<<endl; } ~B() { cout<<"Destructor of B"<<endl; } }; class C: 上市 B { 上市: C() { cout<<"Constructor of C"<<endl; } ~C() { cout<<"Destructor of C"<<endl; } }; class D: 上市 C { 上市: D() { cout<<"Constructor of D"<<endl; } ~D() { cout<<"Destructor of D"<<endl; } }; int main() { D d1; }
输出:
Constructor of A Constructor of B Constructor of C Constructor of D Destructor of D Destructor of C Destructor of B Destructor of A
6.继承示例中的构造函数和析构函数调用
如果一个类具有多重继承,则构造函数的调用将按照顺序进行。
例:
/* * File : constructor_destructor_in_inheritance.cpp * Author : [email protected] * Copyright: @ 前开发者教程.com */ #include<iostream> using namespace std; class A { 上市: A() { cout<<"Constructor of A"<<endl; } ~A() { cout<<"Destructor of A"<<endl; } }; class B { 上市: B() { cout<<"Constructor of B"<<endl; } ~B() { cout<<"Destructor of B"<<endl; } }; class C: 上市 B, A { 上市: C() { cout<<"Constructor of C"<<endl; } ~C() { cout<<"Destructor of C"<<endl; } }; int main() { C c1; }
Constructor of B Constructor of A Constructor of C Destructor of C Destructor of A Destructor of B
7.指针与继承
在C ++中,私有数据成员和公共数据成员存储在连续的内存位置中。因此,指向公共数据成员的指针也将提供对私有数据成员的访问。
派生类也是如此。
当我们将数据存储在堆栈中时,将首先存储基类变量,然后再存储派生类变量。因此,我们获得了派生类数据成员的地址,然后使用该指针访问基本私有类数据成员。如下例所示:
/* * File : pointers_inheritance.cpp * Author : [email protected] * Copyright: @ 前开发者教程.com */ #include<iostream> using namespace std; class A { private: int a; public: A() { a = 10; } }; class B : 上市 A { public: int b; B() { b = 20; } }; int main() { B b1; //pointer to the derived class data member int *ptr = &b1.b; cout<<"The value of variable b is "<< *(ptr)<<endl; //access the base class 私人的 variable ptr --; cout<<"The value of variable a is "<< *(ptr)<<endl; }
输出:
The value of variable b is 20 The value of variable a is 10