今日刷题,无意中发现自己对继承这方面的知识还是很迷茫,弄懂了之后回过头再看依旧容易迷糊,俗话说好记性不如烂笔头,写下来就很nice
主要是子类调用父类的问题,继承的问题,本文将通过代码的方式讲述继承间调用关系
第一部分
以下代码摘自
https://blog.csdn.net/qq_36528804/article/details/87873174?utm_source=app&app_version=4.7.0
#include <iostream>
using namespace std;
class A
{
public:
void h()
{
cout << "public A::h()" << endl;
}
protected:
void g()
{
cout << "protected A::g()" << endl;
}
private:
void f()
{
cout << "private A::f()" << endl;
}
};
class B : public A
{
public:
void fun()
{
// f(); // error: ‘void A::f()’ is private
g();
h();
}
};
int main()
{
B b;
b.fun();
b.f(); // error: ‘void A::f()’ is private
b.g(); // error: ‘void A::g()’ is protected
b.h();
}
1、解析类外
其中B类继承A类:
b.fun(); //调用B类中的fun函数,调用自身函数没有问题
b.f(); //报错,子类可以调用父类函数,但是父类函数为private
b.g(); //报错,子类可以调用父类函数,但是父类函数为protected,保护函数只能在类内使用,在派生类中也可以调用父类protected函数
b.h(); //子类可以调用父类函数,调用成功,因为子类继承同时继承了父类的函数在子类中, 调用的是子类中不可见的h()函数,如果子类重定义了父类函数,那么b.h()将调用自己重定义的函数,如果要调用继承被隐藏函数,需要加域名符如b.A::h();
2、解析类内
B类中fun()函数中调用
f(); //调用的是B类中继承的A类函数,因为在A中该函数为私有,顾无法调用,调用失败
g();
//调用的是B类中继承下来的A类函数,该函数在A中为protected,
且是在类内调用,故可以调用,如在类外则无法调用
h(); //调用的是B类中继承下来的A类函数,该函数在A中为public,且同样是类内调用, 故可以调用,在类外同样可以调用
第二部分
以下代码转自
https://blog.csdn.net/JHXXH/article/details/108766261?utm_source=app&app_version=4.7.0
#include <iostream>
using namespace std;
class A
{
public:
virtual void func()
{
cout <<" this is A" << endl;
}
};
class B : public A
{
public:
virtual void func()
{
cout <<" this is B" << endl;
}
};
int main()
{
A a;
B b;
A* c = new B();
a.func(); //this is A
b.func(); //this is B
b.A::func(); //this is A
c->func(); //this is B
c->A::func(); //this is A
return 0;
}
AB类中函数为虚函数,涉及函数重写,涉及多态,待我细细分析
A* c = new B();
// 涉及多态,是基类指针指向派生类对象,可以调用派生类函数
那么先说说后面的
c->func();
//A类指针指向派生类对象,通过虚表指针查看虚函数表,调用派生类B中重写的函数func(),打印“this is B”
c->A::func();
//因为虚函数重写是多态,且原继承A类的函数地址被新写入的函数覆盖,需要调用,则要用域名符,调用的是A类中的函数,而不是继承下来的函数,调用A类中的函数func()
a.func();
//A类对象调用自身函数,无需多言
b.func();
//B类对象调用重写函数,讲讲原理,和c类似,对象b中有虚表指针在栈上,指向只读数据段rodata中的虚函数表,调用在代码段中的虚函数func()
b.A::func();
//调用的是被覆盖的A中函数,需要加入域名符方可调用
想必对此已有足够的了解了,那么进入我们的第三部分,一起试试叭
第三部分
以下来自牛客网题目
#include
class A
{
public:
void f()
{
cout << “A::f()”;
}
};
class B
{
public:
void f()
{
cout << “B: f()”;
}
void g()
{
cout << “B: g()”;
}
};
class C : public A, public B
{
public:
void g()
{
cout << ”C::g()”;
}
void h()
{
cout << ”C::h()”;
f(); //语句1
}
};
void main()
{
C obj;
obj.f(); //语句2
obj.A::f(); //语句3
obj.B::f(); //语句4
obj.g(); //语句5
}
请问语句1、2、3、4、5中哪些错误呢?
想必聪明的你已经想到了,答案就是语句1和语句2是错的
那么我们来分析一波
语句1:
//位于C类对象中的函数h()中,是可以调用A类中的f函数的,也可以调用B类中的函数的,而且都是public函数,那么为什么不行呢,因为歧义了,系统不知道究竟是调用A还是调用B中的f,自然就报错了
语句2:
//C类对象obj调用继承在C中的函数f,可是同样不知道调用A还是B中的函数,同样产生歧义,报错
语句3和语句4:
//加上了域名符就很清楚的知道调用哪个函数了
语句5:
//调用C类中重定义函数g();因为是C类函数,即使B类继承下来的函数被隐藏也可以调用