这种问题很有意思。
我们都知道派生类对象可以访问基类的属性, 因为是继承(共有),继承基类的属性并在此基础上做扩充。
因此支持派生类对象、指针、引用赋给基类对象, 也叫切片操作、也叫上行转化。
但是基类不能赋给派生类对象, 是不支持的。
你可以强转基类对象为派生类对象指针,进行赋值, 这种操作也叫下行转化,存在安全隐患。
那么如何让基类访问派生类对象独有的属性呢?
1、我想我们应该想想看多态, 这是我第一次想到这个问题的联想。
多态允许我们基类对象访问派生类重写的虚函数, 但是这是要存放在虚表中 的虚函数,且完成重写才可以。
2、第二点, 我们都知道一个对象实例化,当它去访问它的属性时,是通过this指针实现的,如果我们能让基类获取派生的对象的this指针, 不就可以访问派生类的属性了嘛。。。
基于这两点,我想思路已经很明显了, this指针很关键, 多态的目的是让派生类重写虚函数时返回自己的this指针, 这样我们基类对象就可以访问了。
基于原理我们写一段代码作为测试:
#include<iostream>
using namespace std;
//声明
class child;
class Base {
public:
virtual child* Point() {
cout << "不支持操作!" << endl;
//return *(child*)nullptr; //将nullptr转化为child指针类型, 然后解引用。
return nullptr;
}
};
class child : public Base {
public:
//虚函数重写
virtual child* Point() {
return this;
}
//测试函数1
void FUN1() { cout << "hello, i am fun1!!" << endl; }
private:
//测试函数2
void FUN2() { cout << "hello, i am private fun2" << endl; }
};
int main() {
Base* b = new child;
b->Point()->FUN1();
// b->Point()->FUN2(); //不可以访问,就像类外无法访问类内私有属性
return 0;
}
测试结果:
hello, i am fun1!!
上面的FUN1函数和FUN2函数是派生类对象独有的。
基类调用重写后的虚函数的返回值(也就是派生类对象this指针)然后访问到了派生类的成员函数FUN1, 但是不能访问私有成员函数FUN2。
还有其他方法
#include <iostream>
using namespace std;
template<class T>
class Base {
public:
Base() {
T* child_point = (T*)this;
child_point->FUN1();
}
};
class child : public Base<child> {
public:
void FUN1() { cout << "hello, i am FUN1!!" << endl; }
private:
void FUN2() { cout << "hello, i am private FUN2!!" << endl; }
};
int main() {
child ch;
return 0;
}
利用模板类使用,但是感觉这种使用方式不方便。
实例化派生类对象, 利用构造期间调用基类的构造函数,在基类的区域内短暂调用了派生类的属性, 当回到派生类的区域,就gg了。 没有第一种稳定长久。