您的位置:首页 > 健康 > 美食 > C++类的继承(听课笔记)

C++类的继承(听课笔记)

2024/12/27 7:00:56 来源:https://blog.csdn.net/weixin_68539386/article/details/139955508  浏览:    关键词:C++类的继承(听课笔记)
代码1: 子类访问限定、继承方式 ,以及 子类和父类复制兼容
#include<iostream>
using namespace std;//父类和子类是两个独立的作用域
//所以他的属性和方法可以重名class Person//父类
{
public:void Print(){cout << "name:" << _name << endl;cout << "age:" << _age << endl;}
protected:string _name = "peter";
public:int _age = 18;//private成员在子类中不能直接访问//但可以间接获取,例如 Get
};class Student :protected Person//子类 继承方式
{
protected:int _stuid;
};class Teacher :public Person
{
protected:int _jobid;
};// 父类为struct ,子类默认继承方式和访问限定符都是公有的
// 父类为class  ,子类默认继承方式和访问限定符都是私有的struct other :public Person//默认public
{//public
};int main()
{Student s;Teacher t;//s.Print();//public+protected = protected (在类外面不能访问)t.Print();// publuc+publicPerson p = t;//Person p = s;  protected 不能访问//子类可以直接赋值给父类,但是受限制,只有子类的 成员或函数 是 公有public才能//每个子类对象都是一个特殊的父类对象//父类=子类 --> 切割/切片Person& ref = t;//赋值兼容: 不产生临时变量,不用加 const 修饰// ref 就是直接指向切片部分ref._age = 19;//ref可以修改子类(但限制为 public) return 0;
}
代码2: 父类和子类的显示构造函数、构造顺序、析构顺序
#include<iostream>
using namespace std;class Person
{
public:Person(const char* name): _name(name){cout << "Person()" << endl;}Person(const Person& p):_name(p._name){cout << "Person(const Person& p)" << endl;}Person& operator=(const Person& p){cout << "Person& operator=(const Person& p)" << endl;if (this != &p)_name = p._name;return *this;}~Person(){cout << "~Person()" << endl;}
protected:string _name = "peter";
};class Student : public Person
{
public:// 1.如果 子类没有默认构造函数,并且父类也没有默认构造函数,那么在子类的构造函数中必须 显式调用 父类的特定构造函数,否则编译器会报错。// 2.若 子类的构造函数中没有 显式调用 父类的 特定构造函数,那么父类会调用 本身的构造函数 ,若父类没有默认构造函数,否则编译器会报错。Student(const char* Pname, const char* Sname):Person(Pname)//显示调用父类构造函数, _name(Sname){cout << "Student()" << endl;}//Student(const Student& s)   不存在深拷贝时,拷贝构造可以不用写Student(const Student& s):Person(s)//子类可以赋值给父类, _name(s._name){cout << "Student(const Student& s)" << endl;}Student& operator=(const Student& s){cout << "Student& operator=(const Student& s)" << endl;if (this != &s){Person::operator=(s);//和父类重名,父类函数隐藏_name = s._name;}return *this;}~Student(){// ~Person();  此处又不能显示调用// 子类的析构也会隐藏// 因为后期多态,析构函数都会被统一处理成 destructor,导致函数重名// Person::~Person();//即使不写也会自动调用//写了就进行两次析构 (且析构顺序无法是先子类后父类//还是要指定作用域cout << "~Student()" << endl;;;}//构造: 先父类后子类//析构: 先子类后父类void Print(){cout << _name << endl;cout << Person::_name << endl;;//直接指定类域进行访问}
protected:string _name = "lihua";//属性可以重名// Person// 父类+自己,父类的调用父类构造函数初始化(复用)// 父类成员当成一个整体的自定义成员
};int main()
{Student s1("zhangsan", "lisi");//父类 子类s1.Print();//Person()  Student()  lisi  zhangsan//当子类和父类属性重名(只看名称),优先访问当前类域(也称隐藏)cout << endl;Student s2(s1);s2.Print();//Person(const Person& p)  Student(const Student & s)  lisi zhangsan 拷贝构造cout << endl;Student s3("wangwu", "zhaoliu");s3.Print();// Person()  Student()  构造 + 构造cout << endl;Student s4 = s3;s4.Print();//Person(const Person& p)  Student(const Student & s)  拷贝构造cout << endl;Person p("zz");//p.~Person();//显示调用 Person 的析构函数,多次析构return 0;
}
代码3: 类中 静态成员的归属
#include<iostream>
using namespace std;
class Student;
class Person
{
public:Person(){_count++;//可以通过静态成员来计算创建成员个数}friend void Display(const Person& p, const Student& s);//友元不能继承
protected:string _name;
public:static int _count;//静态成员只有一份,子类和父类共用//父类静态成员属于当前类,也属于当前类的所有类
};
int Person::_count = 0;class Student : public Person
{friend void Display(const Person& p, const Student& s);
protected:int _stuNum;//Student 中
};void Display(const Person& p, const Student& s)
{cout << p._name << endl;cout << s._stuNum << endl;
}
int main()
{Person p;Student s;cout << &Person::_count << endl;cout << &Student::_count << endl;//公用一块空间return 0;
}
代码4: 菱形继承问题(虚继承)
//单继承/多继承(父类个数是否唯一
//菱形继承: 多继承的特殊情况(见图)
//问题:  1.数据冗余
//       2.二义性/*
#include<iostream>
using namespace std;class Person
{
public:string _name; // 姓名
};class Student : virtual public Person//虚继承(可有效解决菱形继承问题)
{
protected:int _num; //学号
};class Teacher : virtual public Person
{
protected:int _id; // 职工编号
};class Assistant : public Student, public Teacher
{
protected:string _majorCourse; // 主修课程
};void Test()
{// 这样会有二义性无法明确知道访问的是哪一个Assistant a;a._name = "peter";//Student类和Teacher类都有_name// 需要显示指定访问哪个父类的成员可以解决二义性问题,但是数据冗余问题无法解决a.Student::_name = "xxx";a.Teacher::_name = "yyy";
}int main()
{Test();return 0;
}

以上是关于类的基本定义和基本实现,关于虚函数,可以看我下一篇博客!!!

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com