南宁网站建设产品介绍,买流量平台,ac86u做网站服务器,好用吗目录
类继承
继承的本质
继承的作用
继承的语法
继承的权限
继承的构造析构
继承构造函数
继承析构函数
继承的基类调用
继承的对象赋值
继承与友元关系
继承与静态成员
不能被继承的类
构造函数
语法特性
单继承
单继承的特点
多继承
多继承概念
多继承语…目录
类继承
继承的本质
继承的作用
继承的语法
继承的权限
继承的构造析构
继承构造函数
继承析构函数
继承的基类调用
继承的对象赋值
继承与友元关系
继承与静态成员
不能被继承的类
构造函数
语法特性
单继承
单继承的特点
多继承
多继承概念
多继承语法
多继承初始
菱形继承
菱形继承问题
解决菱形问题 类继承 继承的本质 继承是面向对象编程中的一个重要概念它允许一个类称为派生类或子类从另一个类称为基类或父类继承属性和行为。派生类可以访问基类的非私有成员并且可以添加自己特有的成员和方法。 继承的作用 代码重用继承允许派生类从基类继承属性和行为避免了重复编写相同的代码。层次结构通过继承可以创建类的层次结构体现出不同类之间的关系。多态性继承是实现多态性的基础。基类指针或引用可以指向派生类的对象实现基于继承的多态调用。 继承的语法 class DerivedClass : [访问修饰符] 基类名 //访问修饰符可以是public、protected或private用于指定从基类继承的成员在派生类中的访问权限。
{// 派生类的成员和方法
};//父类(基类)
class Person
{
public:char* m_Name; //姓名int m_Age; //年龄char* m_Class; //课程
};//子类(派生类)
class Teacher : public Person
{
public:char* m_Work; //时间
};//子类(派生类)
class Student : public Person
{
public:char* m_Number; //编号
};继承的权限 public继承基类的public成员在派生类中仍为public基类的protected成员在派生类中仍为protected但对派生类的对象来说基类的private成员不可访问。protected继承基类的public和protected成员在派生类中都变为protected基类的private成员不可访问。private继承基类的public和protected成员在派生类中都变为private基类的private成员不可访问。 #include iostream// 基类
class Base
{
public:int publicVar;void publicMethod() {std::cout Base::publicMethod() std::endl;}protected:int protectedVar;void protectedMethod() {std::cout Base::protectedMethod() std::endl;}private:int privateVar;void privateMethod() {std::cout Base::privateMethod() std::endl;}
};// 派生类 - public继承
class PublicDerived : public Base
{
public:void accessBaseMembers() {publicVar 1; // 可以访问public成员publicMethod(); // 可以访问public方法protectedVar 2; // 可以访问protected成员protectedMethod(); // 可以访问protected方法// privateVar 3; // 错误不能访问private成员// privateMethod(); // 错误不能访问private方法}
};// 派生类 - protected继承
class ProtectedDerived : protected Base
{
public:void accessBaseMembers() {publicVar 1; // 可以访问public成员publicMethod(); // 可以访问public方法protectedVar 2; // 可以访问protected成员protectedMethod(); // 可以访问protected方法// privateVar 3; // 错误不能访问private成员// privateMethod(); // 错误不能访问private方法}
};// 派生类 - private继承
class PrivateDerived : private Base
{
public:void accessBaseMembers() {publicVar 1; // 可以访问public成员publicMethod(); // 可以访问public方法protectedVar 2; // 可以访问protected成员protectedMethod(); // 可以访问protected方法// privateVar 3; // 错误不能访问private成员// privateMethod(); // 错误不能访问private方法}
};int main()
{PublicDerived publicDerived;publicDerived.publicVar 1; // 可以访问public成员publicDerived.publicMethod(); // 可以访问public方法ProtectedDerived protectedDerived;// protectedDerived.publicVar 1; // 错误不能访问public成员// protectedDerived.publicMethod(); // 错误不能访问public方法PrivateDerived privateDerived;// privateDerived.publicVar 1; // 错误不能访问public成员// privateDerived.publicMethod();继承的构造析构 继承构造函数 如果派生类定义了自己的构造函数但没有使用初始化列表调用基类的构造函数则基类的默认构造函数会被隐式调用。如果派生类定义了自己的构造函数并使用初始化列表调用了基类的特定构造函数则基类的该构造函数会被显式调用。 继承析构函数 派生类会自动继承基类的析构函数无需显式定义。在派生类对象销毁时会先调用派生类的析构函数然后自动调用基类的析构函数。 实例代码 #include iostreamclass Base
{
public:Base(){std::cout Base默认构造函数 std::endl;}Base(int nNum){m_Base nNum;std::cout Base有参构造函数 std::endl;}~Base(){std::cout Base析构函数调用 std::endl;}int m_Base;
};class Derived : public Base
{
public:int m_Derived;Derived(){std::cout Derived默认构造函数 std::endl;}Derived(int nNum) : Base(5){m_Derived nNum;std::cout Derived有参构造函数 std::endl;}~Derived(){std::cout Derived析构函数调用 std::endl;}};int main()
{{Derived der(5);}return 0;
}继承的基类调用 使用作用域解析运算符(::)来调用基类的成员函数。 class DerivedClass : public BaseClass {
public:void someFunction() {BaseClass::baseFunction(); // 调用基类的成员函数}
};在派生类中重新定义同名的成员函数覆盖基类的成员函数。 class DerivedClass : public BaseClass {
public:void someFunction() {// 派生类的特定实现}
};使用作用域解析运算符(::)来访问基类的成员变量。 class DerivedClass : public BaseClass {
public:void someFunction() {int value BaseClass::baseVariable; // 访问基类的成员变量}
};重新定义成员变量覆盖基类的成员变量的语法 class DerivedClass : public BaseClass {
public:int derivedVariable; // 重新定义的成员变量覆盖基类的成员变量
};在派生类的成员函数中可以使用作用域解析运算符(::)来访问基类的成员函数和成员变量。 派生类也可以重新定义同名的成员函数和成员变量覆盖基类的成员函数和成员变量。 继承的对象赋值 基类对象不能直接赋值给派生类对象 派生类对象可以赋值给基类的对象(PTR / REF ) - 切片 class Person
{
protected:string _name; // 姓名string _sex; // 性别int _age; // 年龄
};
class Student : public Person
{
public:int _num; // 学号
};
void Test()
{Student sobj;Person pobj sobj;Person* pp sobj;Person rp sobj;
}继承与友元关系 友元关系不能继承也就是说基类友元不能访问子类私有和保护成员 class Student;
class Person
{
public:friend void Display(const Person p, const Student s);
protected:string _name; // 姓名
};class Student : public Person
{
protected:int _stuNum; // 学号
};
void Display(const Person p, const Student s)
{cout p._name endl;cout s._stuNum endl;
}
void main()
{Person p;Student s;Display(p, s);
}继承与静态成员 #include iostreamclass Person
{
public:static int m_static;int m_public;int m_protected;int m_private;
};int Person::m_static 0;class Student : public Person
{
public:int m_public;int m_Student;
};int main()
{std::cout sizeof(Person) std::endl;std::cout sizeof(Student) std::endl;Student::Person::m_static 2;Student s;s.Person::m_public 1;s.m_protected 2;s.m_private 3;s.m_public 4;s.m_Student 5;return 0;
}不能被继承的类 构造函数 将父类的构造函数私有化private这样在子类中是不可见的。当子类对象实例化时会无法调用构造函数 语法特性 C11中增添了final关键字可以将当前类设置为不可被继承无论是否实例化一旦有继承它的会立即报错 代码示例 #include iostreamclass Person final //final声音为不可被继承
{
public://删除基类默认构造函数//Person() delete;private://基类默认函数设置私有//Person(){}
};class Student : public Person
{
public:};int main()
{Student s;return 0;
}单继承 单继承的特点 #include iostream// 基类
class BaseClass {
public:void display() {std::cout BaseClass::display() std::endl;}
};// 派生类
class DerivedClass : public BaseClass {
public:void displayDerived() {display(); // 调用基类的display()函数std::cout DerivedClass::displayDerived() std::endl;}
};int main() {DerivedClass derivedObj;derivedObj.displayDerived();return 0;
}派生类只能从一个基类中继承成员函数和成员变量。派生类可以访问和重写基类的成员函数和成员变量。 多继承 多继承概念 多继承允许一个派生类从多个基类中继承成员和方法。派生类将同时拥有每个基类的成员和方法。 多继承语法 class Derived : access-specifier Base1, access-specifier Base2, ..., access-specifier BaseN {// 类成员和方法声明
};Derived 是派生类的名称。access-specifier 可以是 public、protected 或 private用于指定基类成员的访问权限。Base1, Base2, ..., BaseN 是基类的名称用逗号分隔。 多继承初始 派生类的构造函数负责调用每个基类的构造函数来初始化继承的基类部分。 构造函数的调用顺序与基类在派生类中的声明顺序相同与构造函数初始化列表中的顺序无关。 析构函数的调用顺序与构造函数相反即先调用派生类的析构函数然后是每个基类的析构函数。 #include iostreamclass Base1
{
public:Base1(){std::cout Base1 std::endl;}int m_Base;
};class Base2
{
public:Base2(){std::cout Base2 std::endl;}int m_Base;
};class Derived : public Base1, public Base2
{
public:Derived(){std::cout Derived std::endl;}int m_Base;
};int main()
{Derived d;d.Base1::m_Base 1;d.Base2::m_Base 2;d.m_Base 3;return 0;
}菱形继承 ---------| Base |---------/ \/ \
------ ------
| D1 | | D2 |
------ ------\ /\ /-------|Derived|-------Base 是基类。D1 和 D2 是直接派生类它们分别通过不同的路径从基类继承。Derived 是最终派生类继承自 D1 和 D2。 菱形继承问题 数据冗余由于 D1 和 D2 都继承自 Base当 Derived 继承自 D1 和 D2 时Derived 中会包含两份 Base 类的成员。二义性如果 Base 类有一个虚函数 foo()D1 和 D2 都覆盖了这个虚函数Derived 如何确定调用哪个版本的 foo() 解决菱形问题 虚继承是一种特殊的继承方式用于解决菱形继承的问题。 使用关键字 virtual 声明继承关系可以确保在继承链中只有一个共享的基类实例。 虚继承可以避免数据冗余和二义性的问题。 #include iostream// 基类 Base
class Base {
public:int data;
};// D1 通过虚继承继承 Base
class D1 : virtual public Base {
};// D2 通过虚继承继承 Base
class D2 : virtual public Base {
};// Derived 继承自 D1 和 D2
class Derived : public D1, public D2 {
};int main() {Derived derived;derived.data 10;std::cout derived.data std::endl; // 输出10return 0;
}