关于c++多态的测试(带详细注释)

最近学习c++多态和继承方面的东西,写下来方便记忆,欢迎指正

#include <iostream>
#include <string>
using namespace std;
class Base{
public:
	int a;
	static int b;//在类中声明的static变量必须在类外部再定义一次!,否则无法被调用.在类内不能初始化static成员(除了const成员),只能在类外
	Base()
	{
		abc te;
		a = 15;
		te.i = 10;
	}
	class abc{
	public:
		int i;
	};
	//函数不能同时为virtual和static
	virtual void test(){ cout << "this is parent test" << endl; }//基类一旦声明为虚函数,且子类对此函数均为重写
	//当用基类对象访问此函数时,会转到子类定义的函数中.
	void test1(){ cout << "this is parent test1" << endl; }
	virtual int glh() = 0;//纯虚函数必须在子类中实现
	//static函数是全局类的函数,由于函数不能同时为virtual和static,所以static函数不能被重写
	static void read() { cout << "this is parent read,value is " << b++ << endl; }//static函数在类内部或外部定义均可

};
int Base::b = 88;//必须在类外再次定义,并可以初始化
//void Base::read(){ cout << "this is parent read,value is " << b << endl; }//static函数只能访问static成员变量
class Derived :public Base{
public:
	Derived()
	{
		a = 19;
	}
	virtual void test(){//这里不管加不加virtual,base->test();都会执行到这里,但是参数类型和数量和返回类型必须与基类的函数相同,否则相当于重新定义了一个函数
		cout << "this is Derived son test" << endl;}//如果注释掉此函数,则基类指针会调用基类的base->test();
	void test(string &str){ cout << "this is Derived son test,value is " << str << endl; }//此函数不能被基类直接访问到
	void test1(){ cout << "this is Derived son test1" << endl; }//此函数不能被基类直接访问到,如果注释掉此函数,那么sobase.test1();
	//会被报错,因为子类定义的同名函数void test1(string &str)(不管参数相不相同,只要函数名相同,子类即覆盖了继承自基类对应的函数),如果想
	//访问基类的test1,一.将void test1(string &str)注释掉,防止覆盖;二.
	void test1(string &str){ cout << "this is Derived son test1,value is " << str << endl; }//此函数不能被基类直接访问到
	static void read(){ cout << "this is son read,value is " << b++ << endl; }//在子类可以重载基类static函数,但同样无法使用基类指针访问
	void write(){ cout << "this is son write" << endl;}
	int glh(){ a = 3; return 1; }
};
//总结:如果子类想通过基类指针访问自己定义的函数,那么需要将基类的对应函数声明称virtual重写此函数,但是此指针是无法访问子类其余的重载函数,如
//Derived的test1(),只能通过子类的对象进行访问.
//为什么要把子类的指针赋值给父类?如Base *base = &sobase;
//我个人估计一年或者几年之后你又会问“如何隐藏类的定义,让用户看不到类的实现细节”或者“如何让用户无法修改类的私有成员”。
//一个办法就是用子类型多态。
//在父类定义所有需要用到的接口(公共成员函数)和允许用户看到的数据,把父类暴露给用户。而在子类中定义实现细节,用户不知道子类的定义——甚至
//不知道子类叫什么名字,将来哪怕完全替换掉子类的实现,换成另一个子类,用户也会一无所知。最后需要做的就是写一个函数来返回“子类指针”了
//——因为我们不想让用户知道子类的任何信息,所以函数不能不能直接声明成返回子类对象或者返回“子类指针”,正确的做法是声明成返回父类指针,
//而实际上,却是把子类指针转换成父类指针然后返回.这就是virtual的用处了.
int main()
{
	int n;
	string str("python");
	Derived sobase;
	Base *base = &sobase;
	cout << base->a << endl;//19
	base->test();//this is Derived son test
	base->test1();//this is parent test1,同下
	base->read();//b == 88
	//base->test1(str);//如果在子类中重载基类的函数,那么使用基类的指针是无法访问此重载函数的,编译器报错
	sobase.test1();//如果想访问子类重载基类的函数,必须用子类的对象去访问
	sobase.test1(str);//如果想访问子类重载基类的函数,必须用子类的对象去访问
	sobase.read();//b == 89
	Derived ssbase;
	ssbase.read();//b == 90,可以看出b是全局的,不随对象的变化而变化

	return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值