C++:关于你想知道的继承,都在这里

今日刷题,无意中发现自己对继承这方面的知识还是很迷茫,弄懂了之后回过头再看依旧容易迷糊,俗话说好记性不如烂笔头,写下来就很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类继承下来的函数被隐藏也可以调用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值