记录C++中,子类同名属性并不能完全覆盖父类属性的问题

问题代码:

首先看一段代码:很简单,就是BBB继承自AAA,然后BBB重写定义了同名属性,然后调用父类AAA的打印函数:

cpp 复制代码
#include <iostream>
using namespace std;

class AAA {
public:
	AAA() {}
	~AAA() {}
	
	void func() {
		YourVar = 20;
	}
	
	void print() {
		cout << "YourVar: " << YourVar << endl;
	}
	
public:
	int YourVar = 10;
	
};

class BBB : public AAA {
public:
	BBB() {
		YourVar = 20;
	}
	~BBB() {}
	
	void print1() {
		cout << "YourVar: " << YourVar << endl;
	}
	
	void YourMethodOrFunction() {}
	
private:
	int YourVar;
};

int main() {
	BBB b;
	b.print();
	//b.print1();
	
	cout << "********" << endl;
	
	return 0;
}

打印结果:

会发现,明明我构造函数里面将YourVar的值改为了20,但是还是打印的10.

这个问题,属于C++的基础问题,我记得,子类继承父类,如果子类中,定义了同名属性的话,那么父类的属性会被隐藏,访问子类的那个属性,就是子类的,不会是父类的。

但是如果父类里面,有一个打印的函数print,会发现,这个print函数,生效的范围,只有父类,不包括子类。只有将父类的print函数重写,才能生效在子类中:

解决思路1:重写print

cpp 复制代码
#include <iostream>
using namespace std;

class AAA {
public:
	AAA() {}
	~AAA() {}
	
	void func() {
		YourVar = 20;
	}
	
	void print() {
		cout << "YourVar: " << YourVar << endl;
	}
	
public:
	int YourVar = 10;
	
};

class BBB : public AAA {
public:
	BBB() {
		YourVar = 20;
	}
	~BBB() {}
	
	void print() {
		cout << "YourVar: " << YourVar << endl;
	}
	
	void YourMethodOrFunction() {}
	
private:
	int YourVar;
};

int main() {
	BBB b;
	b.print();
	
	cout << "********" << endl;
	
	return 0;
}

打印结果:

虽然解决了问题,但是明明我父类中,写了print函数,干嘛还重新写一次?还有意义?

解决思路2:去掉子类的同名属性

cpp 复制代码
#include <iostream>
using namespace std;

class AAA {
public:
	AAA() {}
	~AAA() {}
	
	void func() {
		YourVar = 20;
	}
	
	void print() {
		cout << "YourVar: " << YourVar << endl;
	}
	
public:
	int YourVar = 10;
	
};

class BBB : public AAA {
public:
	BBB() {
		YourVar = 20;
	}
	~BBB() {}
	
	
//private:
//	int YourVar;
};

int main() {
	BBB b;
	b.print();
	
	cout << "********" << endl;
	
	return 0;
}

但是有时候,我们就是要这么重写,那么该怎么办呢?

解决思路3:将父类地址传递给子类

cpp 复制代码
#include <iostream>
using namespace std;

class AAA {
public:
	AAA() {
		YourVar = new int;
		*YourVar = 10;
	}
	~AAA() {
		delete YourVar;
	}
	
	void print() {
		cout << "YourVar: " << *YourVar << endl;
	}
	
protected:
	int *YourVar;
};

class BBB : public AAA {
public:
	BBB() {

		// 将父类地址传递给子类
		YourVar = AAA::YourVar;
		*YourVar = 20;
	}
	~BBB() {}
	
private:
	int *YourVar;
};

int main() {
	
	BBB b;
	b.print();
	
	cout << "********" << endl;
	
	return 0;
}

解决思路4:将子类地址传递给父类:

cpp 复制代码
#include <iostream>
using namespace std;

class AAA {
public:
	AAA() {
		// YourVar = new int;
		// *YourVar = 10;
	}
	~AAA() {
		delete YourVar;
	}
	
	void print() {
		cout << "YourVar: " << *YourVar << endl;
	}
	
protected:
	int *YourVar;
};

class BBB : public AAA {
public:
	BBB() {
		YourVar = new int;
		// 将子类地址传递给父类
		AAA::YourVar = YourVar;
		*YourVar = 20;
	}
	~BBB() {}
	
private:
	int *YourVar;
};

int main() {
	
	BBB b;
	b.print();
	
	cout << "********" << endl;
	
	return 0;
}

总结

  1. 面对这样的情况,要么就不要写同名属性(但有时候不能保证自己忘记了)

  2. 当以后继承的类层次很多的时候,难免会定义同名属性,但是父类的函数,是不会访问子类的同名属性的,这个是这个问题的关键。虽然在子类中,父类的属性确实是隐藏了,但隐藏不代表消失,也不代表父类的函数中,也将这个属性给隐藏或者替换了。

  3. 要么就使用指针,将父类和子类的地址变成一样的地址。

  4. 虽然最后一种比较麻烦,但是会惊奇的发现,如果是指针的话,可以实现父类中实现所有操作,子类只管创建对象和使用,子类如果想改实现,根据需要同名替代即可。甚至属性也可以写成函数指针那些,是一种非常灵活的使用方式,是一种上层设计模式的简单体现。

cpp 复制代码
#include <iostream>
using namespace std;

class AAA {
public:
	AAA() {
		// YourVar = new int;
		// *YourVar = 10;
	}
	~AAA() {
		delete YourVar;
	}
	
	void print() {
		cout << "YourVar: " << *YourVar << endl;
	}
	
protected:
	int *YourVar;
};

class BBB : public AAA {
public:
	BBB() {
		YourVar = new int;
		// 将子类地址传递给父类
		AAA::YourVar = YourVar;
		*YourVar = 20;
	}
	~BBB() {}
	
	void print() {
		cout << "*********************" << endl;
		cout << "YourVar: " << *YourVar << endl;
		cout << "*********************" << endl;
	}
	
private:
	int *YourVar;
};

int main() {
	
	BBB b;
	b.print();
	
	return 0;
}
相关推荐
微学AI3 小时前
一根针指向所有方向:挂谷猜想对 LLM Agent 技能-记忆架构的启示
开发语言·人工智能·架构·挂谷猜想
豆瓣鸡4 小时前
算法日记 - Day3
java·开发语言·算法
韭菜炒鸡肝天5 小时前
VTK开发笔记(一):VTK介绍,Qt..+VSx+VTK.编译
开发语言·笔记·qt
小王C语言5 小时前
【7. 实现登录注册模块】:实现会话管理、注册/登录/退出 API
网络·c++
Aaron - Wistron5 小时前
Web API C# (Furion版)带 单元测试
开发语言·后端·c#
Dxy12393102166 小时前
Python项目打包成EXE完整教程(PyInstaller实战避坑)
开发语言·python
0566467 小时前
Python康复训练——常用标准库
开发语言·python·学习
骊城英雄7 小时前
基于C#+avalonia ui实现的跨平台点胶机灌胶监控控制上位机软件
开发语言·ui·c#
吾儿良辰7 小时前
一个被BCL遗忘的高性能集合:C# CircularBuffer<T>深度解析
开发语言·windows·c#
昆曲之源_娄江河畔7 小时前
Python如何安装flask, pymssql
开发语言·python·flask·pymssql