C++ Pirmer第十五章③
C++ Primer
面向对象程序设计
继承中的类作用域
来一段很精彩的总结:
- 每个类定义自己的作用域,在这个作用域内我们定义类的成员。
- 当存在继承关系时,派生类的作用域嵌套在其基类的作用域内。
- 如果一个名字在派生类的作用域内无法正确解析,则编译器将继续在外层的基类作用域中寻找该名字的定义 我们看一段之前的书店折扣类的代码:
我们来看看isbn是怎么解析的:Bulk_quote bulk; cout << bulk.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++工程师#