我有一个简单的 C++ 基类、派生类示例。
// Base.hpp
#pragma once
class Base
{
public:
virtual float getData();
virtual void setData(float a, float b);
virtual void setData(float d);
protected:
float data;
};
//Base.cpp
#include "stdafx.h"
#include "Base.hpp"
float Base::getData()
{
return data;
}
void Base::setData(float a, float b)
{
setData(a);
}
void Base::setData(float d)
{
data = d;
}
//Derived.hpp
#pragma once
#include "Base.hpp"
class Derived
: public Base
{
public:
virtual void setData(float d);
};
//Derived.cpp
#include "stdafx.h"
#include "Derived.hpp"
void Derived::setData(float d)
{
data = d + 10.0f;
}
如果我现在创建一个指向 Base 的指针,则可以正常编译。
//Main.cpp
#include "stdafx.h"
#include "Base.hpp"
#include "Derived.hpp"
Base *obj = new Derived();
但是如果我指向派生类,编译器(VC 2008 和 2010)会提示:
Main.cpp(12): error C2660: 'Derived::setData' : function does not take 2 arguments
下面是导致这个错误的代码:
//Main.cpp
#include "stdafx.h"
#include "Base.hpp"
#include "Derived.hpp"
Derived *obj = new Derived();
似乎基类方法被隐藏了。我的印象是,由于基类方法是虚拟的,即使从 Derived 指针查看它们也应该是可见的,或者我错了吗?
请您参考如下方法:
这是 C++ 名称查找的神器。基本算法是编译器将从当前值的类型开始并沿着层次结构向上处理,直到找到具有目标名称的类型的成员。然后它将只对具有给定名称的该类型的成员进行重载决策。它不考虑父类型上的同名成员。
解决这个问题的方法是重新定义 Derived
上的函数,并将它们转发到 Base
class Derived {
...
void setData(float a, float b);
}
void Derived::setData(float a, float b) {
Base::setData(a,b);
}
此外,您可以使用 using
声明将基本成员引入作用域
class Derived {
using Base::setData;
...
}
关于使用 using 的文档