Effective C++读书笔记

条款32:确定public继承塑造出is-a关系

如果你另class D以public形式继承class B,你便告诉编译器(以及你的代码阅读者)说,你D的每一个对象同时也是类型为B的一个对象.

public继承遇到的问题:

class Bird{
    public:
        virtual void fly(); //bird can fly
        ...
    };
 class Penguin:public Bird{    //Penguin is a kind of bird
        ...
 };
企鹅(penguin)是一种鸟是事实,鸟可以飞也是事实,但这个继承体系说企鹅可以飞,显然不严谨

既然不是所有的鸟都可以飞,就这样处理继承体系:

class Bird{
        ...//没有声明fly函数
    };
class FlyingBird:public Bird{
    public:
        virtual void fly();
        ...
};
    class Penguin:public Bird{
        ...  //没有声明fly函数
    };

存在于classes之间的关系,is-a,has-a,is-implemented-in-terms-of(根据某物实现出)

请记住:

★★"public继承"因为is-a.适用于base class身上的每一件事情一定也适用与derived class身上,因为每一个derived class对象也都是一个base class对象.

条款33,避免遮掩,继承而来的名称


class Base { 
private: 
    int x; 
public: 
    virtual void mf1() = 0; 
    virtual void mf1(int); 
    virtual void mf2(); 
    void mf3(); 
    void mf3(double); 
}; 
class Derived : public Base { 
public: 
    virtual void mf1(); 
    void mf3(); 
    void mf4(); 
};

以作用域为基础的“名称遮掩规则”并没有改变,因此base class内所有名为mf1和mf3的函数都被derived class内的mf1和mf3函数遮掩掉了。

Derived d; 
int x; 
d.mf1(); 
d.mf1(x);//错误,Derived::mf1遮掩了Base::mf1 
d.mf2(); //调用base::mf2() 
d.mf3(); 
d.mf3(x);//错误,Derived::mf3遮掩了Base::mf3

即使base class和derived classes内的函数有不同的参数类型也适用,而且不论函数是virtual或non-virtual也适用,和函数里的double x遮掩全局int x一样,Derived内的函数mf3遮掩了一个名称为mf3但类型不同的函数

这些事防止你建立derived class时附带的从疏远的base classes继承重载函数,如果想继承重载函数 则使用using

列:

你可以用using声明式达成目标:

class Derived : public Base { 
public:
//base class内的public名称在publicly derived class内也应该是public。 
    using Base::mf1;    // 让base class内为mf1和mf3的所有东西 
    using Base::mf3;    //在Derived class作用域内都可见(并且public) 
    virtual void mf1(); 
    void mf3(); 
    void mf4(); 
};
Derived d; 
int x; 
d.mf1(); 
d.mf1(x);//现在没问题了,调用Base::mf1 
d.mf2(); 
d.mf3(); 
d.mf3(x);//现在没问题了,调用Base::mf3

这意味着如果你继承base class并加上重载函数,而你又希望重新定义或覆写(推翻)其中一部分,那么你必须为那些原本会被覆盖的每一个名称引入一个using声明式,否则某些你希望继承的名称会被覆盖。

★假设Derived以private形式继承Base,而Derived唯一想继承mf1是哪个无参数版本,using声明将排不上用场,因为using声明会令继承而来的某给定名称之所有同名函数在derived class中都可见,实现这一功能需要不同的技术:转交函数(forwarding function)

class Base{
public:
	virtual void mf1() = 0;
	virtual void mf1(int);
    ...//与前同
};
class Derived:private Base
{
public:
	virtual void mf1()
	{
		Base::mf1();
	}
	...
};
...
Derived D;
int x = 10;
D.mf1();//很好,调用的是Derived::mf1()
D.mf1(x)//错误Base::mf1()被遮掩了







posted @ 2012-04-17 21:27  foreverlearn  阅读(135)  评论(0编辑  收藏  举报