当前位置: 首页 > news >正文

继承(2),咕咕咕!

(1)继承与友元

友元关系不能继承,基类友元不能访问派生类私有和保护成员。

class student;
class person
{
public:
friend void display(const person& p,const student& s);
protected:
string name;
};class student:public person
{
protected:
int stuid;
};void display(const person& p,const student& s)
{
cout<<p.name<<endl;
cout<<s.stuid<<endl;
}int main()
{
person p;
student s;
//编译报错,student::stuid无法访问protected成员
//把display函数也变成student的友元函数就行了
display(p,s);
return 0;
}

2.继承与静态成员

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

class person
{
public:
string name;
static int count;
};int person::count=0;class student:public person
{
protected:
int stuid;
};int main()
{
person p;
student s;
//这里可以看到非静态成员name的地址不一样
//派生类继承下来,父派生类对象各有一份
cout<<&p.name<<endl;
cout<<&s.name<<endl;
//这里的运行结果看到静态成员count的地址一样
//派生类和基类共用同一份静态成员
cout<<&p.count<<endl;
cout<<&s.count<<endl;
//公有的情况下,父派生类指定类域都可以访问静态成员
cout<<person::count<<endl;
cout<<student::count<<endl;
return 0;
}

3.多继承以及菱形继承问题

单继承:一个派生类只有一个直接基类

多继承:一个派生类有两个或以上直接基类。多继承对象在内存中的模型是,先继承的基类在前面,后继承的基类在后面,派生类的成员在最后。

菱形继承:菱形继承是多继承的一种特殊情况。菱形继承的问题是有数据冗余和二义性。在assistant的对象中person成员会有2份,支持多继承就一定会有菱形继承,实践中不建议。

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;
};
int main()
{
assisiatnt a;
a.name="gugu";//编译报错,对name的访问不明确,要显示指定基类的成员,但是数据冗余未解决a.studnet::name="1";
a.teahcer::name="0";
}

4.虚继承

虚继承的底层实现比较复杂,性能也会有一定损失。

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;
};
int main()
{
//使用虚继承解决数据冗余和二义性
assisiatnt a;
a.name="gugu";
}

虽然有时候虚继承可以解决菱形继承的问题,但是还是不建议用菱形继承,因为虚继承来解决也会有新的问题。

class person
{
public:
person(const char* name):name(name){}
string name;
};
class student:virtual public person
{
public:
student(const char* name,int num):person(name),num(num){}
protected:
int num;
};
class teacher:virtual public person
{
public:
teacher(const char* name,int id):person(name),id(id){}
protected:
int id;
};
//不建议菱形继承的例子,因为会变复杂
//在虚继承中,最顶层的基类(这里是person)的构造函数不由中间派生类(student/teacher)调用,
//而是由最终派生类(assistant)直接调用。
class assistant:public student,public teacher
{
public:
assistant(const char*name1,const char* name2,const char* name3)
:person(name3),student(name1,1),teacher(name2,2)
{}
protected:
string majorcourse;
};int main()
{
assistant a("gugu","gugugu","gugugugu");//最后是gugugu,只初始化了第一个
return 0;
}

多继承还有指针偏移的现象。

class base1{public:int b1;};
class base2{public:int b2;};
class derive:public base1,public base2{public:int d;};
int main()
{
derive d;
base1* p1=&d;
base2* p2=&d;
derive* p3=&d;
}p1=p3!=p2 p1/p3->----------------|              ||--------------|              p2->----------------

IO库中的菱形虚拟继承
template<class charT,class Traits=std::char_traits<charT>>
class basic_ostream:virtual public std::basic_ios<charT,Traits>{};
template<class charT,class Traits=std::char_traits<charT>>
class basic_istream:virtual public std:basic_ios<charT,Traits>{};

5.继承和组合

public是一种is-a关系,每个派生类对象都是一个基类对象

组合是一种has-a关系,假设B组合了A,每个B对象都有一个A对象

继承允许根据基类的定义来定义派生类的实现。这种通过生成派生类的复用称为白箱复用。在继承方式中,基类的内部细节对派生类可见。继承一定程度破坏了基类的封装,基类的改变对派生类有很大的影响。派生类和基类的依赖关系很强,耦合性高。

对象组合是类继承外另一种复用选择。新的更复杂的功能可以通过组装或组合对象来获得。对象组合要求被组合的对象有良好定义的接口,称为黑箱复用,对象的内部不可见,组合之间没有强伊依赖关系,耦合性低,优先使用对象组合有助于保持类的封装性。

类之间的关系就适合is-a就用继承,要实现多态就用继承。类之间的关系既适用于is-a又适用于has-a优先使用组合。

//has-a关系
class tire
{
protected:
string brand;
size_t size'
};
class car
{
protected:
string colour;
string num;
tire t1;
tire t2;
tire t3;
tire t4;
};
//is-a关系
class gugu:public car
{
public:
void drive(){cout<<"gugu"<<endl;}
};

http://www.dtcms.com/a/524841.html

相关文章:

  • C++编程技巧和规范_9_引用计数解析
  • android11禁止安装apk
  • 深入了解linux网络—— 自定义协议(下)
  • 金麦建站官网成都视频剪辑培训
  • 【C++闯关笔记】详解多态
  • 数据库技术指南(二):MySQL CURD 与高级查询实战
  • 用mvc做网站报告做做做网站
  • 设置一个自定义名称的密钥,用于 git 仓库上下传使用
  • MAC Flood与ARP Flood攻击区别详解
  • 高兼容与超低延迟:互联网直播点播平台EasyDSS直播服务如何成为直播点播应用的“技术底座”?
  • MongoDB 集群优化实战指南
  • wordpress网站速度检测医院做网站需要多少钱
  • iOS 26 查看电池容量与健康状态 多工具组合的工程实践
  • 机器学习(10)L1 与 L2 正则化详解
  • 保险网站建设平台与别人相比自己网站建设优势
  • vscode中好用的插件
  • PCB过电流能力
  • 【数据库】KingbaseES数据库:首个多院区异构多活容灾架构,浙人医创新开新篇
  • 嵌入式软件算法之PID闭环控制原理
  • 性价比高seo网站优化免费下载模板的网站有哪些
  • 无棣网站制作襄樊网站制作公司
  • AI服务器工作之电源测试
  • 《Muduo网络库:实现Acceptor类》
  • 第十三篇《TCP的可靠性:三次握手与四次挥手全解析》
  • SSE 流式响应实战:如何在 JavaScript 中处理 DeepSeek 流式 API
  • 在线阅读网站开发教程品牌建设促进会是什么工作
  • 一站式服务门户网站充值支付宝收款怎么做
  • 网站建设超速云免费小程序源码php
  • 如何裁剪u-boot,保留其必要功能,使体积尽可能小
  • 借助智能 GitHub Copilot 副驾驶 的 Agent Mode 升级 Java 项目