标签:继承 提高 变量 str 可见 private 重写 lis 无法
目录
定义相似的类型并对其建模,形成一种层次关系
基类——一般、泛化派生类——具体、细化
继承的意义
理由:
当delete一个动态分配的对象指针时,将执行析构函数,如果指针指向的是继承体系的类型,
可能出现指针的静态类型与动态类型不符的情况,
此时将可能调用了错误版本的析构函数,产生未定义行为
重载: 同一作用域,函数名相同而形参列表不同
覆盖: 派生类对继承来的函数进行重新定义——对函数体的修改
隐藏: 内层作用域定义同名函数,形参列表随意——即使形式上能与外层作用域同名函数形成重载,但实际上在内层作用域中,能看到的仅有此函数,外层同名者被隐藏
类的继承会形成一个嵌套关系:基类为外层作用域,派生类为内层作用域,
可用using形成重载
若产生冲突(参数列表一样),将优先调用内层作用域所定义的
必须被已被定义,
因为派生类需要它的成员,
同时另一个隐含——类不能派生自自身
class和struct的区别仅为类成员的默认访问权限与默认继承权限,前者为private,后者为public
类成员权限控制符——控制用户(普通用户和派生类)的访问权限
private:用户不可访问
protected:普通用户不可访问,派生类及派生类友元可访问
派生类成员和派生类友元只能通过派生类对象(类内仅是省略了this)访问基类protected成员,而不能通过基类对象访问
class A
{
protected:
int a;
};
class B
{
public:
void f(A a) { a.a; } // 错误,不能通过基类对象访问
void f() { a; } // 正确,实际也是this->a;
void f(B b) { b.a; } // 正确
};
public:任何用户都可访问
类继承权限控制符——控制派生类的用户(普通用户和派生类的派生类)的访问权限——对派生类没有影响
继承权限控制——派生类到基类的转换
派生类到基类的转换:基类指针或引用指向派生类
A *ap = new B; // 如果可行,那么用户代码就突破了private和protected的限制,通过ap访问B中本不可访问成员
智能指针也支持派生类到基类的转换
静态类型:编译时已知,由变量声明时类型或表达式生成的类型确定
动态类型:运行时可知,对象或表达式在内存中的类型
继承体系中,基类的指针或引用能绑定到派生类对象上,所以其静态类型和动态类型可能不一致
一个对象、引用或指针的静态类型决定了其可见成员
一个类定义自己的作用域
继承体系中:派生类的作用域嵌套与基类的作用域中
名字查找——由对象的静态类型确定查找的作用域
找到后常规类型检查,调用是否合法,重载
若合法,根据是否为虚函数
隐藏:内层同名隐藏外部同名——即使能产生重载,也no matching
? 若希望形成重载,使用using 将外层作用域函数引入内层作用域
? 若产生冲突(参数列表一样),将优先调用内层作用域所定义的
class NoDerived final { /* */ };
class Base { /* */};
class Last final : Base { /* */ };
辅助类
class A;
class Assistant
{
private:
Assistant();
friend class A;
};
class A : public virtual Assistant // 虚拟继承理由:
// 非虚拟继承时,B构造调用A构造,A调用Assistant构造,可正常进行,无法阻止继承
// 虚拟继承时,Assistant的构造函数将由B寻址调用,private无法进行
{
};
class B : public A
{
public:
B(){} // 实际不自己定义,编译器将合成一个deleted的默认构造函数
};
int main()
{
A a;
B b; // 错误,Assistant::Assistant() is private in this contex
}
标签:继承 提高 变量 str 可见 private 重写 lis 无法
原文地址:https://www.cnblogs.com/YanceW/p/11706328.html