如何通过基类的虚调用访问派生类的protected clone函数?
关于《Accelerated C++》13章句柄类中protected虚clone的调用问题
嘿,这个问题刚好是书中句柄类实现的核心细节,我来给你一步步讲清楚怎么解决~
首先得明确咱们的目标:Student_Info作为句柄类,要实现深拷贝,避免多个句柄共享同一个底层对象的问题。而clone虚函数就是用来让底层对象(不管是Core还是Grade)自己创建一个完全一样的副本,这也是虚函数多态性的典型应用。
为什么protected的clone能被虚调用?
首先要记住C++里的protected访问规则:基类的protected成员可以被基类自身、基类的友元,以及所有派生类的成员函数访问。而我们的关键操作是在Student_Info里调用clone,所以第一步要让Student_Info成为Core(以及Grade)的友元,这样它就能合法访问protected的clone函数了。
具体实现步骤
1. 定义基类Core的clone函数
在Core里声明一个protected的虚clone,让它返回一个新的Core对象副本:
class Core { // 让句柄类能访问protected的clone friend class Student_Info; // 其他成员(比如name、midterm等)... protected: // 虚函数,返回当前对象的副本 virtual Core* clone() const { return new Core(*this); } // 其他protected成员... };
2. 在派生类Grade中重写clone
Grade作为Core的派生类,同样声明protected的clone,但返回Grade类型的副本(这里可以用协变返回类型,也就是返回Grade*而非Core*,C++允许虚函数返回派生类指针,只要它是基类返回类型的子类):
class Grade : public Core { // 同样让句柄类访问 friend class Student_Info; // 额外成员(比如final_exam等)... protected: // 重写基类的clone,返回Grade对象副本 Grade* clone() const override { return new Grade(*this); } // 其他protected成员... };
3. 在Student_Info的拷贝构造中调用clone
Student_Info内部持有一个Core*指针(指向Core或Grade对象),在拷贝构造时,我们通过这个指针调用clone——因为clone是虚函数,会根据指针实际指向的对象类型,动态调用对应的clone函数:
class Student_Info { public: // 默认构造函数 Student_Info() : p(nullptr) {} // 拷贝构造函数:调用clone创建深拷贝 Student_Info(const Student_Info& other) : p(other.p ? other.p->clone() : nullptr) {} // 别忘了赋值运算符也要做类似处理(RAII风格) Student_Info& operator=(const Student_Info& other) { if (this != &other) { // 先释放当前对象 delete p; // 调用clone创建新副本 p = other.p ? other.p->clone() : nullptr; } return *this; } // 析构函数释放底层对象 ~Student_Info() { delete p; } private: Core* p; // 指向Core或Grade的底层对象 };
关键原理拆解
- 友元声明:让
Student_Info能突破protected权限,合法调用clone函数。 - 虚函数动态绑定:当调用
other.p->clone()时,不管p的静态类型是Core*,只要它实际指向的是Grade对象,就会调用Grade::clone,返回一个Grade的副本,完美实现了“什么类型的对象就拷贝什么类型”的需求。 - protected的意义:把
clone设为protected,是为了封装——只有负责管理对象生命周期的句柄类(Student_Info)和派生类自己能调用它,外部代码不能随意创建对象副本,保证了类的封装性。
内容的提问来源于stack exchange,提问作者Chris Jing
相关产品推荐
相关产品推荐

