C++ Pirmer第十五章③

C++ Primer

面向对象程序设计

继承中的类作用域

来一段很精彩的总结:

  • 每个类定义自己的作用域,在这个作用域内我们定义类的成员。
  • 当存在继承关系时,派生类的作用域嵌套在其基类的作用域内。
  • 如果一个名字在派生类的作用域内无法正确解析,则编译器将继续在外层的基类作用域中寻找该名字的定义 我们看一段之前的书店折扣类的代码:
    Bulk_quote bulk;
    cout << bulk.isbn();
    
    我们来看看isbn是怎么解析的:
  • 因为我们是通过Bulk_quote的对象来调用isbn的,所以首先在Bulk_quote中查找,没找到
  • 因为Bulk_quote是Disc_quote的派生类,所以接下来在Disc_quote中找,没找到
  • 接下来在Quote中找,找到了

我们来看个看上去不科学,但是很合法的有意思的事情:

class Disc_quote : public Quote
{
public:
    //返回最大折扣的数量和价格
    pair<size_t, double> discount_policy() const {return {quantity, discount};}
}
//好的,我们来访问这个函数
Bulk_quote bulk;
//用两个不同的类型指针去接bulk的地址
Bulk_quote *bulkP = &bulk;
Quote *itemP = &bulk;

bulkP->discount_policy(); //可以访问
itemP->discount_policy(); //不可以

为什么会这样呢,想想类作用域就知道了

名字冲突与继承:局部覆盖整体

和普通的函数一样的:

struct Base
{
    Base() : mem(0) {} //构造函数
protected:
    int mem;
};
struct Derived : Base
{
    Derived(int i) : mem(i){}
    int get_mem() {return mem;}

protected:
    int mem; //跟基类的重名
};
Derived d(42);
cout << d.get_mem() << endl; //打印42

//我们当然也可以强行打印0,只要把派生类中的函数这样定义就好了(强行)
int get_base_mem() {return Base::mem;}

派生类和基类有重名函数,不存在重载的哦

struct Base
{
    void f()
    {
        cout << "Base";
    }
};
struct Derived : Base
{
    void f(int) //隐藏了基类的f函数,只要函数名相同就隐藏,其他无所谓
    {
        cout << "Derived";
    }
};
Derived d;
Base b;
b.f(); //打印Base
d.f(1); //打印Derived
d.f(); //错了:d自己的不能用,还把基类能用的隐藏了
d.BAse::f(); //正确:打印Base

虚函数与作用域

记不记得我们原来要求基类与派生类中的虚函数要有相同的形参列表,因为加入基类和派生类的虚函数接受的实参不同,那我们就没办法通过基类的引用或指针调用派生类的虚函数了:

class Base
{
public:
    int fcn(int) //与类中下面的虚函数同名,必须要形参不同才能重载
    {
        cout << "Base不虚" << endl; 
    }
    virtual int fcn()
    {
        cout << "Base虚" << endl;
    }        
};

class D1 : public Base 
{
public:
    int fcn(int) //并不是虚函数,因为参数和基类不同
    {
        cout << "D1不虚" << endl;
    }

    int fcn() //这才是虚函数,虽然没写override,更好的习惯是写上,这里为了迷惑你们就不写了
    {
        cout << "D1虚" << endl;
    }
};


int main()
{
    Base bobj; D1 d1obj;
    Base *bp1 = &bobj; 
    Base *bp2 = &d1obj;
    D1 *bp3 = &d1obj;
    bp1->fcn(); //Base虚
    bp2->fcn(); //D1虚
    bp3->fcn(); //D1虚
    bp1->fcn(1); //Base不虚
    bp2->fcn(1); //Base不虚
    bp3->fcn(1); //D1不虚
    system("pause"); //提交的时候不要这句
    return 0;
}

你要是看得懂上面6个结果,说明你的虚函数,动态绑定,重载,作用域什么的已经掌握了,加油吧

#C++工程师#
全部评论

相关推荐

鬼迹人途:你去投一投尚游游戏,服务器一面,第一个图算法,做完了给你一个策略题,你给出方案他就提出低概率问题,答不上当场给你挂
点赞 评论 收藏
分享
05-29 20:34
门头沟学院 C++
KarlAllen:得做好直接春招的准备。学历差的话,一是面试要求会比学历好的严格不少,二是就算面试通过了也会被排序。总之暑期和秋招对于学历差的就是及其不友好
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
06-19 17:02
鼠鼠深知pdd的强度很大,但是现在没有大厂offer,只有一些不知名小厂我是拒绝等秋招呢,还是接下?求大家帮忙判断一下!
水中水之下水道的鼠鼠:接了再说,不图转正的话混个实习经历也不错
投递拼多多集团-PDD等公司10个岗位 >
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务