继承多态常见类型题目

本文深入探讨了C++中的面向对象编程概念,包括类的构造与析构顺序、重载、隐藏与覆盖的区别、类型转换、虚表机制、多态调用条件等关键知识点。同时,还讨论了基类指针指向子类对象时的行为,以及由此引发的内存布局、虚函数调用和析构函数问题。
摘要由CSDN通过智能技术生成

1、类的编译顺序,类的构造顺序,子类构造顺序,子类析构顺序

类的编译顺序:类名 ---> 成员名 ---> 方法体

子类的构造顺序:先构造父类,再构造子类

子类的析构顺序:先析构子类,再析构父类

2、重载,隐藏,覆盖

重载:1、作用域相同

           2、函数名相同

           3、参数列表不同

隐藏:子类隐藏父类同名的方法

覆盖:子类覆盖父类相同的虚成员方法

3、四种类型强转

  • const_cast
  • static_cast
  • dynamic_cast
  • reinpreter_cast

4、虚表什么时候产生?存放在哪里?

在编译期产生,存放在.rodata段

5、动多态、静多态

静多态:编译期决定的多态,如:模板、重载

动多态:运行期间决定的多态,如:继承中的多态

6、动多态调用的条件有什么?

  1. 指针调用,或引用调用
  2. 该类型下的虚函数
  3. 对象完整

7、基类指针指向子类对象,指针是什么类型?*指针是什么类型?(基类中有虚函数)

父类:A 子类:B

指针:class A*类型

*指针:class B类型

class A
{
public:
	virtual void Show()
	{
		cout << "A" << endl;
	}
};
class B : public A
{
	void Show()
	{
		cout << "B" << endl;
	}
};
int main()
{
	A* a = new B;
	cout << typeid(a).name() << endl;
	cout << typeid(*a).name() << endl;
	return 0;
}

8、基类存在虚函数,子类覆盖,子类的内存布局

9、基类无虚函数,子类有虚函数。将基类指针指向子类对象时,其指向子类对象中基类起始的部分。

10、基类定义虚函数和普通重载函数,子类定义同名函数隐藏普通函数和函数

class Base
{
public:
	//以下两个函数构成重载
	void show()
	{
		cout << "Base: void show()" << endl;
	}
	virtual void show(int i)
	{
		cout << "Base: virtual void show(int)" << endl;
	}
};

class Derive : public Base
{
public:
	void show()//隐藏父类中的void show();
	{
		cout << "Derive: void show()" << endl;
	}
};
int main()
{
	Base* base = new Base;
	Derive* derive = new Derive;
	base->show();
	base->show(10);
	derive->show();
	derive->Base::show();
	return 0;
}

11、基类指针指向堆上的子类对象,此时delete指针,子类析构函数未调用,有可能造成内存泄漏。基类析构函数应写成虚函数

12、基类构造清除所有数据,基类指针调用自己的虚函数,子类调用虚函数

class Base
{
public:
	Base()
	{
		memset(this, 0, sizeof(Base));
	}

	virtual void show()
	{
		cout << "Base::virtual void show()" << endl;
	}
};
/*
vfptr 00000000
*/

class Derive : public Base
{
public:
	Derive()
		:Base()
	{
	}
	void show()
	{
		cout << "Derive::void show()" << endl;
	}
};

int main()
{
	Base *pb = new Base();
	pb->show();//执行出错。当基类构造的时候将空间内所有字节都置为0,
                   //包括vfprt,当访问虚函数的时候就会进入地址为0的空间,访问出错。

	Derive* pd = new Derive();
	pd->show();//正常执行,虽然基类构造的时候将空间内所有字节包括vfptr都置为0,
                   //但是子类在构造的时候将vfprt又置为自己的Show函数入口地址,因此访问正常

	return 0;
}

13、基类和派生类的构造函数、析构函数中调用虚函数,不会产生多态调用  不会,因为此时对象不完整(对象在构造函数结束到析构函数之前是完整的)

14、基类虚函数放到公有,派生类虚函数放到私有,外部基类指针指向子类对象,能否派生类私有函数否访问?

       可以,因为该指针是基类的指针,但是其又可以指向子类的示例,因此在调用之前(进入虚函数表中函数地址之前)无法确定调用的究竟是谁

class Base
{
public:
	virtual void show(int)
	{
		cout << "Base :: virtual void show(int)" << endl;
	}
};

class Derive : public Base
{
public:

private:
	void show(int)
	{
		cout << "Derive :: void show(int)" << endl;
	}
};

int main()
{
	Base* pb = new Derive();
	pb->show(10);

	return 0;
}

15、基类和子类给不同的虚函数函数参数默认值,基类指针指向子类对象,调用函数。

此时会调用子类的函数,但是函数的参数默认值是基类中函数的参数默认值

class Base
{
public:
	virtual void show(int a = 20)
	{
		cout << "a=" << a << "==================" << endl;
	}
};

class Derive : public Base
{
public:
	void show(int a = 30000)
	{
		cout << "a=" << a << endl;
	}
};

int main()
{
	Base*p = new Derive();
	p->show();//此时会打印:a = 20;

	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值