C ++继承,隐藏基本方法

时间:2010-09-29 15:45:39

标签: c++ oop inheritance

我有一个简单的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();

但是如果我指向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指针查看它们也应该是可见的,或者我错了吗?

2 个答案:

答案 0 :(得分: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 :(得分:3)

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

如果您真的希望该名称的基类函数可见,您可以添加一个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);
};

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