(继承及其访问限定符)&&(派生类及其默认成员函数)&&(赋值兼容规则)

◆继承:

★继承概念

继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能。这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。

继承定义格式

★继承关系&访问限定符

class Base

{

public:

Base()

{

cout<<"B()" <<endl;

}

~Base ()

{

cout<<"~B()" <<endl;

}

void ShowBase()

{

cout<<"_pri = " <<_pri<< endl;

cout<<"_pro = " <<_pro<< endl;

cout<<"_pub = " <<_pub<< endl;

}

private:

int _pri;

protected:

int _pro;

public:

int _pub;

};

class Derived:public Base

{

public:

Derived()

{

cout<<"D()"<<endl;

}

~Derived ()

{

cout<<"~D()"<<endl;

}

void ShowDerived()

{

cout<<"_d_pri = "<<_d_pri<< endl;

cout<<"_d_pro = "<<_d_pro<< endl;

cout<<"_d_pub = "<<_d_pub<< endl;

}

private:

int _d_pri;

protected:

int _d_pro;

public:

int _d_pub;

};


总结:

  1. 基类的private成员在派生类中是不能被访问的,如果基类成员不想在类外直接被访问,但需要在派生类中能访问,就定义为protected。可以看出保护成员限定符是因继承才出现的。
  2. public继承是一个接口继承,保持is-a原则,每个父类可用的成员对子类也可用,因为每个子类对象也都是一个父类对象。
  3. protetced/private继承是一个实现继承,基类的部分成员并非完全成为子类接口的一部分,是 has-a 的关系原则,所以非特殊情况下不会使用这两种继承关系,在绝大多数的场景下使用的都是公有继承。
  4. 不管是哪种继承方式,在派生类内部都可以访问基类的公有成员和保护成员,基类的私有成员存在但是在子类中不可见(不能访问)。
  5. 使用关键字class时默认的继承方式是private,使用struct时默认的继承方式是public,不过最好显示的写出继承方式。
  6. 在实际运用中一般使用都是public继承,极少场景下才会使用protetced/private继承.

◆派生类的默认成员函数

在继承关系里面,在派生类中如果没有显示定义这六个成员函数,编译系统则会默认合成这六个默认的成员函数。

【继承关系中构造函数调用顺序】

【说明】

1、基类没有缺省构造函数,派生类必须要在初始化列表中显式给出基类名和参数列表。

2、基类没有定义构造函数,则派生类也可以不用定义,全部使用缺省构造函数。

3、基类定义了带有形参表构造函数,派生类就一定定义构造函数。

【继承关系中析构函数调用过程】

class Test1

{

public:

Test1( int data){cout <<"Test1()"<<endl;}

~Test1 (){cout<< "~Test1()"<<endl ;}

};

class Test2

{

public:

Test2( int data){cout <<"Test2()"<<endl;}

~Test2 (){cout<< "~Test2()"<<endl ;}

};

class Base1

{

public:

Base1( int data): _data(data )

{cout <<"Base1()"<<endl;}

~Base1 (){cout<< "~Base1()"<<endl ;}

protected:

int _data;

};

class Base2

{

public:

Base2( int data): _data2(data )

{cout <<"Base2()"<<endl;}

~Base2 (){cout<< "~Base2()"<<endl ;}

protected:

int _data2;

};

class Derive: public Base1, public Base2

{

public:

//Derive(): Base1(0), Base2(1),t1(3), t2(4)

//Derive(): Base2(0), Base1(1),t2(3), t1(4)

//Derive(): t1(3), t2(4), Base1(0), Base2(1)

Derive(): t2 (3), t1 (4), Base2 (0), Base1()

{cout <<"Derive()"<<endl;}

~Derive (){cout<< "~Derive()"<<endl ;}

protected:

Test1 t1;

Test2 t2;

};


  • 继承体系中的作用域
  1. 在继承体系中基类和派生类是两个不同作用域。
  2. 子类和父类中有同名成员,子类成员将屏蔽父类对成员的直接访问。(在子类成员函数中,可以使用 基类::基类成员 访问)--隐藏 --重定义
  3. 注意在实际中在继承体系里面最好不要定义同名的成员。

class Person

{

public:

Person( const char * name = "" , int id = 0)

: _name(name ), _num( id)

{}

protected:

string _name;          // 姓名

int _num;              // 身份证号

};

class Student: public Person

{

public :

Student(const char * name,  int id, int stuNum)

: Person(name , id ), _num(stuNum )

{}

void DisplayNum()

{

cout<<" 身份证号: "<<Person :: _num<< endl ;

cout<<" 学号"<< _num << endl ;

}

protected :

int _num ;              // 学号

};

★继承与转换--赋值兼容规则--public继承

  1. 子类对象可以赋值给父类对象(切割/切片)
  2. 父类对象不能赋值给子类对象
  3. 父类的指针/引用可以指向子类对象
  4. 子类的指针/引用不能指向父类对象(可以通过强制类型转换完成)

★友元与继承

友元关系不能继承,也就是说基类友元不能访问子类私有和保护成员。

class Person

{

friend void Display(Person &, Student&s);

protected :

string _name ;          // 姓名

};

class Student: public Person

{

protected :

int _stuNum ;      // 学号

};

void Display(Person &, Student &s)

{

cout<<p._name<<endl;

cout<<s._name<<endl;

cout<<s._stuNum<<endl;

}

void TestPerson1()

{

Person p;

Student s;

Display (p, s);

}

★继承与静态成员

基类定义了static成员,则整个继承体系里面只有一个这样的成员。无论派生出多少个子类,都只有一个static成员实例。

class Person

{

public :

Person(){++ _count;}

protected :

string _name ;          // 姓名

public :

static int _count;      // 统计人的个数。

};

int Person::_count = 0;

class Student : public Person

{

protected :

int _stuNum ;      // 学号

};

class Graduate :public Student

{

protected:

string _seminarCourse;      // 研究科目

};

void TestPerson1()

{

Student s1;

Student s2;

Student s3;

Graduate s4;

cout<<"人数:"<<Person::_count<<endl;

Student ::_count = 0;

cout<<"人数:"<<Person::_count<<endl;

}

 ★单继承&多继承&菱形继承

【单继承】

一个子类只有一个直接父类时称这个继承关系为单继承。

【多继承】

一个子类有两个或以上直接父类时称这个继承关系为多继承

【菱形继承】

class Person

{

public :

string _name ;   // 姓名

};

class Student : public Person

{

protected :

int _num ;   //学号

};

class Teacher : public Person

{

protected :

int _id ;     // 职工编号

};

class Assistant : public Student, public Teacher

{

protected :

string _majorCourse ;     // 主修课程

};

void Test ()

{

// 显示指定访问哪个父类的成员

Assistant a ;

a.Student ::_name = "xxx";

a.Teacher ::_name = "yyy";

}

  • 虚继承--解决菱形继承的二义性和数据冗余的问题
  1. 虚继承解决了在菱形继承体系里面子类对象包含多份父类对象的数据冗余&浪费空间的问题。
  2. 虚继承体系看起来好复杂,在实际应用我们通常不会定义如此复杂的继承体系。一般不到万不得已都不要定义菱形结构的虚继承体系结构,因为使用虚继承解决数据冗余问题也带来了性能上的损耗。

(继承及其访问限定符)&&(派生类及其默认成员函数)&&(赋值兼容规则)

时间: 2024-10-17 23:19:13

(继承及其访问限定符)&&(派生类及其默认成员函数)&&(赋值兼容规则)的相关文章

(继承及其访问限定符)&amp;&amp;(派生类及其默认成员函数)&amp;&amp;(赋值兼容规则)

◆继承: ★继承概念 继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能.这样产生新的类,称派生类.继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程. 继承定义格式 ★继承关系&访问限定符 class Base { public: Base() { cout<<"B()" <<endl; } ~Base () { cout<<"~

C++类的默认成员函数

成员函数隐含this指针参数: 每成员函数一个隐式的指针形参(构造函数除外): 对象在调用成员函数时,编译器会将对象的地址传递给this指针: 1.构造函数(需用一个公有成员函数对私有的成员变量进行初始化,在对象构造时执行一次,无参的构造函数和带缺省值的构造函数都是缺省构造函数 ,缺省的构造函数只能有一个) Mystring(const char *str="")//带缺省值的构造函数 { _str = new char[strlen(str) + 1]; strcpy(_str, s

【继承与多态】C++:继承中的赋值兼容规则,子类的成员函数,虚函数(重写),多态

实现基类(父类)以及派生类(子类),验证继承与转换--赋值兼容规则: 子类对象可以赋值给父类对象(切割/切片) 父类对象不能赋值给子类对象 父类的指针/引用可以指向子类对象 子类的指针/引用不能指向父类对象(可以通过强制类型转换完成) #include<iostream> using namespace std; class People    //父类或者基类 { public:     void Display()     {         cout << "_na

各个访问限定符的权限范围

访问限定符:类内部 同一个包的其他类 其他包的子类 其他包的其他类public 可访问 可访问 可访问 可访问protected 可访问 可访问 可访问 不可访问不写 可访问 可访问 不可访问 不可访问private 可访问 不可访问 不可访问 不可访问 原文地址:https://blog.51cto.com/14232274/2432143

C#继承机制 继承与访问修饰符

继承与访问修饰符 访问修饰符是一些关键字,用于指定声明的成员或类型的可访问性.类的继承中有四个访问修饰符: public protected internal private.使用这些访问修饰符可指定下列五个可访问性级别: public protected internal internal protected private. 1.继承中关于可访问域的一些问题 基类的所有成员(实例构造函数.析构函数和静态构造函数除外)都由派生类型继承.这甚至包括基类的私有成员.但是,私有成员的可访问域只包括声

【总结】C++基类与派生类的赋值兼容规则

在初步探索了C++继承的语言特性之后,总结下其赋值兼容规则: 1.子类对象可以赋值给父类对象(切割/切片) 在公有继承的前提下,子类是可以赋值给父类对象的,为什么是共有继承(public),因为公有继承会产生"is-a"的关系,这种关系会导致子类中有结构的嵌套这父类的信息,.所以子类可以给父类赋值,期间会发生类似降级的事情,使得赋值成功.若为私有继承,则会产生"has-a"的关系,这种关系是从属关系,基类中的数据仅仅是包含在派生类中,若赋值,则不会产生类似于降级的事

C# - 阻止派生类重写虚成员

1 using System; 2 3 namespace 类_阻止派生类重写虚成员 4 { 5 // 声明一个抽象类Animal(用abstract关键字声明抽象类) 6 public abstract class Animal 7 { 8 // 基类的抽象方法Voice(); 功能在派生类实现 9 public abstract void Voice(); 10 } 11 12 // 派生类(子类)继承自Animal 13 // 14 public class Horse : Animal

基类和派生类之间的同名函数处理方式

[基类和派生类之间的同名函数处理方式] class A { public: void fn() {} void fn(int a) {} }; class B : public A { public: void fn() {} }; int main() { B b; b.fn(3); // 编译失败,编译器会报怨,B中,并不存在fn(int)的函数). return 0; } 这里涉及到一个C++中的重要的知识点.即:同名函数的重载动作,只发生在自由函数(即非成员),及同一个class/str

C++语言笔记系列之十六——赋值兼容规则&amp;多继承的二义性

1.赋值兼容规则 (1)派生类对象可以给基类对象赋值,这种情况下派生类对象将从基类继承的成员的值赋值给一个基类对象:但是不允许将一个基类的对象赋值给一个派生类. (2)可以将派生类对象的地址赋给基类指针,使基类指针指向派生类对象,通过基类指针引用成员时只可以引用派生类从基类继承而来的成员,而不允许引用派生类的新成员. (3)引用与指针相同. 2.多继承 (1)一个派生类从两个以上的基类中去继承. (2)说明: class 派生类名:继承方式 基类1, 继承方式 基类2,...... {派生类成员