`
kmplayer
  • 浏览: 508894 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

条款43:明智地使用多继承

阅读更多
1,多继承带来的一个根本性的复杂性:模棱两可.
例如:
#include <iostream>
using namespace std;

class Lottery
{
public:
    virtual void draw() { cout << "Lottery" << endl; }
};
class GraphicalObject
{
public:
    virtual void draw() { cout << "GraphicalObject" << endl; }
};

class LotterySimulation: public Lottery, public GraphicalObject  //多重继承
{
  // doesn't declare draw
};


int main()
{
    LotterySimulation *pls = new LotterySimulation;
    //pls->draw();                   // 模棱两可
    pls->Lottery::draw();          // fine
    pls->GraphicalObject::draw();  // fine
    return 0;
}

注:纵使其中一个继承的draw函数时private属性,依旧模棱两可.
原因:"存取限制"不能解除"因多继承而得之members"的模棱两可状态.
理由:改变某个class成员的可存取性,绝不应该连带改变程序的意义.

2,即使这么改了,依旧存在问题:
#include <iostream>
using namespace std;

class Lottery
{
public:
    virtual void draw() { cout << "Lottery" << endl; }
};
class GraphicalObject
{
public:
    virtual void draw() { cout << "GraphicalObject" << endl; }
};

class LotterySimulation: public Lottery, public GraphicalObject  //多重继承
{
  // doesn't declare draw
};

class SpecialLotterySimulation: public LotterySimulation
{
public:
    virtual void draw() { cout << "SpecialLotterySimulation" << endl; }
};



int main()
{
    LotterySimulation *pls = new SpecialLotterySimulation;
    //pls->draw();                   // 依旧模棱两可
    pls->Lottery::draw();          // fine
    pls->GraphicalObject::draw();  // fine
    return 0;
}

3,一个绕弯的解决方法:
#include <iostream>
using namespace std;

class Lottery
{
public:
    virtual void draw() { cout << "Lottery" << endl; }
};
class GraphicalObject
{
public:
    virtual void draw() { cout << "GraphicalObject" << endl; }
};

class AuxLottery: public Lottery
{
public:
    virtual void lotteryDraw() = 0;
    virtual void draw() { lotteryDraw(); }
};
class AuxGraphicalObject: public GraphicalObject
{
public:
    virtual void graphicalObjectDraw() = 0;
    virtual void draw() { graphicalObjectDraw(); }
};
//注:这两个函数的作用就是为继承而来的draw函数声明一个新名称.

class LotterySimulation: public AuxLottery, public AuxGraphicalObject
{
public:
    virtual void lotteryDraw() { cout << "Lottery Part." << endl; }
    virtual void graphicalObjectDraw() { cout << "GraphicalObject Part." << endl; }
};

int main()
{
    LotterySimulation *pls = new LotterySimulation;

    Lottery *pl = pls;
    GraphicalObject *pgo = pls;
    pl->draw(); // this calls LotterySimulation::lotteryDraw
    pgo->draw();// this calls LotterySimulation::graphicalObjectDraw
    return 0;
}

4,看下面这个"钻石"



如果你不希望D对象内含多份A成员,那么上述的B和C都将A声明为一个virtual base class.
当A是一个nonvirtual base时,D对象的典型内存布局:



当A是一个virtual base时,D对象的典型内存布局,其中内含两个指针:



5,当virtual base class需要引用计数时:
引用计数被指定于这一base派生类最深的classes的成员初值表.
最简单的办法:避免virtual base classes拥有data成员.

看下面的例子:
A定义了虚拟函数mf(),C重新定义了mf,B和D没有重新定义mf.

D调用哪个mf?直接继承自C的那个,还是间接调用A的那个.
答案:
如果A是B或C的nonvirtual基类,上述调用模棱两可.
如果是virtual基类:调用C::mf.

6,实用:如果你可以避免实用virtual base(避免"钻石"继承),事情会好处理得多.
看一个实例:



class PersonInfo //利用它的实现,private inheritance
{
public:
PersonInfo(DatabaseID pid);
virtual ~PersonInfo();
virtual const char * theName() const;
virtual const char * theBirthDate() const;
virtual const char * theAddress() const;
virtual const char * theNationality() const;
virtual const char * valueDelimOpen() const;       // see
virtual const char * valueDelimClose() const;      // below
};

const char * PersonInfo::valueDelimOpen() const
{
return "[";                   // default opening delimiter
}
const char * PersonInfo::valueDelimClose() const
{
return "]";                   // default closing delimiter
}

class Person  //利用它的接口:public inheritance
{                  
public:                            
virtual ~Person();                
virtual string name() const = 0;
virtual string birthDate() const = 0;
virtual string address() const = 0;
virtual string nationality() const = 0;
};

class MyPerson: public Person, private PersonInfo // multiple inheritance

public:
MyPerson(DatabaseID pid): PersonInfo(pid) {}
//虚函数,重新定义
const char * valueDelimOpen() const { return ""; }
const char * valueDelimClose() const { return ""; }
// 重用PersonInfo的实现
string name() const
{ return PersonInfo::theName(); }
string birthDate() const
{ return PersonInfo::theBirthDate(); }
string address() const
{ return PersonInfo::theAddress(); }
string nationality() const
{ return PersonInfo::theNationality(); }
};
  • 大小: 12.4 KB
  • 大小: 11.4 KB
  • 大小: 12.7 KB
  • 大小: 17.9 KB
分享到:
评论

相关推荐

    Effective.C++.中文第二版.50条款doc文档.chm

    条款43: 明智地使用多继承 条款44: 说你想说的;理解你所说的 第七章 杂项 条款45: 弄清C++在幕后为你所写、所调用的函数 条款46: 宁可编译和链接时出错,也不要运行时出错 条款47: 确保非局部静态对象在使用前被...

    高效C++:从C到C++

    **条款33:明智地使用内联** - **背景**:`inline`关键字用于指示编译器尝试内联函数调用。 - **原因**:过度使用`inline`可能会导致代码膨胀。 - **示例**: ```cpp inline int add(int a, int b) { return a +...

    Effective C++(第三版)

    条款39:明智而审慎地使用private继承 use private inheritance judiciously. 条款40:明智而审慎地使用多重继承 use multiple inheritance judiciously. 7. 模板与泛型编程 templates and generic programming ...

    Effective C++ 中文版

    内容简介: 有人说C++程序员可以分成两类,读...条款39:明智而审慎地使用private继承 条款40:明智而审慎地使用private继承 7.模板与泛型编程 8.定制new和delete 9.杂项讨论 A 本书之外 B 新旧版条款对映 索引

    c++pdf.zip

    3. **利用const**:使用const关键字来指定函数不会修改对象,提高代码可读性和安全性。 4. **选择适当的继承方式**:单一继承和多重继承各有优劣,理解它们的差异并根据需求选择。 5. **理解运算符重载**:谨慎地...

    八年级政治下册第三单元我们的文化经济权利单元综合测试题3新人教版.doc

    这篇文档是针对八年级学生的一份政治学科综合测试题,主要涵盖了我们的文化、经济...这些知识点涉及了公民的基本权利、义务教育、财产权、消费者权益、遗产继承等多个方面,都是中学生需要理解和掌握的重要法律知识。

    最新新担保借款合同书范本关于借款合同的保证担保合同精品热门模板word.docx

    8. **特殊情况处理**:如借款人出现死亡、失踪或丧失民事行为能力,合同规定了继承人、受遗赠人、监护人或财产代管人的责任。 9. **法律效力**:合同一旦签订,即具有法律效力,对双方均有约束力,因此在签订前应...

    婚前财产协议范本2精选.doc

    此文档“婚前财产协议范本2精选.doc”提供了详细的条款,帮助即将结婚的男女双方避免因财产问题引发的潜在矛盾。以下是协议中涉及的主要知识点: 1. **个人财产界定**:协议明确了男方和女方各自婚前已有的房产,...

    八年级政治上册第三单元我们的朋友遍天下单元综合测试题3新人教版.doc

    在没有遗嘱的情况下,张某的儿子、女儿和母亲作为第一顺序继承人有权继承遗产,而弟弟和妹妹作为第二顺序继承人,在第一顺序继承人存在时无法继承。 2. **受教育权与法律责任**:小辉认为受教育与否是个人权利,但...

    C++经典书籍之一(Think in C++,effectiveC++ )

    条款16则讨论了如何明智地选择动态内存分配,避免内存泄漏。 学习这两本书,不仅可以巩固C++的基本知识,还能深入了解其高级特性和最佳实践。《Think in C++》提供了扎实的理论基础,《Effective C++》则指导如何在...

    中融信托依云小镇信托贷款集合资金信托计划合同.doc

    这份合同详细规定了信托计划的各种条款和条件,涉及到信托的设立、管理、风险分配、收益分配等多个方面。 1. **信托目的**:信托的目的通常是为投资者提供一种投资渠道,通过信托公司将资金贷款给特定项目,期望...

    最新个人承包工程合同下载实用版个人承包合同WORD格式模板2021.docx

    4. **继承条款**:合同双方中的任何一方去世,其法定继承人将继续履行合同。 5. **国家征地补偿**:如果果园土地被国家依法征用,土地补偿费归甲方,而果树补偿费和复耕费等归乙方。固定设施补偿费则按投资方归属。 ...

    员工入股协议书范本.pdf

    同时,还应保证员工的知情权,确保员工充分理解入股条款和潜在的风险,从而作出明智的投资决策。在实际操作中,公司的人力资源部门和法务部门应协同工作,确保协议书的公正性和合法性,以免在公司与员工之间引起不必...

    【财务资金管理 】中融中城建号信托贷款集合资金信托计划资金信托合.pdf

    15. **其他条款**:合同中还可能包含一些特定的条款,如通知方式、不可抗力处理等,以确保合同的完整性和执行性。 这份合同详细规定了信托计划的各个方面,为参与其中的委托人、受托人和受益人提供了清晰的权利和...

    保险学原理考点知识点.doc

    8. **保险合同**:保险合同具有保障性、附合性(条款由保险人制定)、射幸性(基于不确定因素)和最大诚信原则。合同形式包括投保单、暂保单、保险凭证、保险单等。 9. **保险合同订立原则**:包括保险利益原则...

    精品资料(2021-2022年收集)工商银行开户流程网银版.doc

    【工商银行开户流程-网银版】的文档主要涵盖了金融领域中的...这些内容对于理解黄金投资的基本特点和优势,以及了解工商银行的网银服务有很好的指导作用,对于投资者来说尤其重要,可以帮助他们做出更明智的投资决策。

    最新个人向公司借款合同范本下载经典版单位间借款合同范本DOC格式文本.docx

    4. **合同的终止条件**:第十六条规定了合同提前到期的情况,如借款人违约、丧失民事行为能力或无继承人等情况,贷款人有权要求提前偿还全部或部分贷款本息。 签订此类合同时,双方必须清楚了解条款内容,确保自身...

    私募基金基金合同范本.docx

    ### 私募基金合同关键知识点解析 #### 一、前言 - **目的与依据**:合同旨在明确规定各方当事人的权利义务,确保基金合法合规运作,并保护投资...对于潜在的投资者来说,理解这些条款对于做出明智的投资决策至关重要。

Global site tag (gtag.js) - Google Analytics