C++中基类继承函数访问派生类静态成员的问题
问题:派生类调用基类GetFoo返回值不符合预期
我定义了基类Parent,包含受保护的静态成员foo(值为0)和非静态成员函数GetFoo以返回该静态成员的值。派生类Child继承Parent,并重新定义静态成员foo的值为1:
class Parent { protected: static const int foo = 0; public: int GetFoo() { return foo; } }; class Child : Parent { protected: static const int foo = 1; };
调用Child实例的GetFoo函数时,预期返回派生类的静态成员值1,但实际返回基类的0:
int main(int argc, char* argv[]) { Child child(); std::cout << child.GetFoo(); }
输出结果为0。以下是问题分析和解决方案:
初始理解的错误点
- 静态成员的重定义是隐藏而非覆盖:基类的
foo和派生类的foo是两个完全独立的静态成员,派生类的foo只是隐藏了基类的同名成员,并没有覆盖它。基类函数中引用的foo只会指向基类自己的静态成员。 - 非虚函数的静态绑定特性:
GetFoo是基类的非虚成员函数,C++对非虚函数采用静态绑定——编译器在编译阶段就确定了要调用的是Parent::GetFoo,不管调用这个函数的对象实际是基类还是派生类实例,都会执行基类版本的函数,返回基类的foo值。 - 额外陷阱:函数声明而非对象创建:代码中
Child child();并不是创建Child对象,而是声明了一个名为child、返回Child类型的无参函数。不过这不是导致返回0的核心原因,即使修正为Child child;,输出依然是0。
实现预期效果的方案
方案1:派生类重写GetFoo函数
直接在派生类中重新定义GetFoo函数,返回自身的静态成员foo:
#include <iostream> class Parent { protected: static const int foo = 0; public: virtual int GetFoo() // 声明为虚函数,支持多态调用 { return foo; } }; class Child : public Parent // 建议使用public继承,符合常规语义 { protected: static const int foo = 1; public: int GetFoo() override // 用override关键字明确标记重写,避免错误 { return foo; } }; int main() { Child child; std::cout << child.GetFoo() << std::endl; // 输出1 // 多态场景下也能正确返回派生类的值 Parent* ptr = &child; std::cout << ptr->GetFoo() << std::endl; // 输出1 return 0; }
方案2:利用CRTP(奇异递归模板模式)
通过CRTP让基类直接访问派生类的静态成员,无需虚函数也能实现静态绑定下的正确返回:
#include <iostream> template<typename Derived> class Parent { protected: static const int foo = 0; public: int GetFoo() { // 直接访问派生类的静态成员 return Derived::foo; } }; class Child : public Parent<Child> { protected: friend class Parent<Child>; // 允许基类访问派生类的protected成员 static const int foo = 1; }; int main() { Child child; std::cout << child.GetFoo() << std::endl; // 输出1 return 0; }
内容的提问来源于stack exchange,提问作者Red Needle
相关产品推荐
相关产品推荐

