2010-09-29 115 views
5

我有一个简单的C++基类,派生类的例子。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(); 

看来,基类方法正在被隐藏。我的印象是,由于基类方法是虚拟的,即使从派生指针查看它们也应该是可见的,或者我错了吗?

+0

你的派生类是什么样的? – 2010-09-29 15:49:25

+1

[Overlading a Base's Overloaded Function in C++]可能的重复(http://stackoverflow.com/questions/888235/overriding-a-bases-overloaded-function-in-c) – 2010-09-29 15:49:46

回答

11

这是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; 
    ... 
} 
使底座成员纳入范围

关于此使用的文档

+1

也许你可以添加一个提示'使用'? – sbi 2010-09-29 15:50:59

+0

@sbi,良好的通话。新增 – JaredPar 2010-09-29 15:53:28

+0

@Jerry,谢谢修复 – JaredPar 2010-09-29 16:20:25

3

派生类中的函数将在基类中隐藏任何具有相同名称的函数。

如果你真的想要这个名字的基类的功能(S)是可见的,你可以添加一个using声明做到这一点:

class Base { 
public: 
    void setData(float d); 
    void setData(float d, float e); 
}; 

class Derived : public Base { 

    using Base::setData; 

    void SetData(float d); 
}; 

[修订:]看来我的记忆是错误的。这不会引起歧义 - 即使使用声明,Derived::setData优先(可以这么说),所以当您在派生对象上调用setData(float)时,您会得到Derived::setData(float)。如果您将其设为虚拟并通过指向Base的指针调用,您仍然可以获得Derived::setData(float);

+0

是的,这是我走的路,'+ 1'(尽管Jared更彻底地解释了原因)。 – sbi 2010-09-29 16:14:55