2010-09-29 59 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