C ++方法只有在对象转换为基类时才可见?

时间:2010-01-14 22:40:43

标签: c++

它必须是我的代码中特定的内容,我无法发布。但也许有人可以提出可能的原因。

基本上我有:

class CParent
{
 public:
  void doIt(int x);
};
class CChild : public CParent
{
 public:
  void doIt(int x,int y,int z);
};

CChild *pChild = ...
pChild->doIt(123); //FAILS compiler, no method found
CParent *pParent = pChild;
pParent->doIt(123); //works fine

到底是怎么回事?

编辑:人们在谈论阴影/隐藏。但是两个版本的doIt具有不同数量的参数。当然不能混淆编译器,子类中的重载哪些不可能与父类版本混淆?可以吗?

我得到的编译器错误是: 错误C2660:'CChild :: doIt':函数不带1个参数

7 个答案:

答案 0 :(得分:29)

你已经隐藏了一个方法。例如:

struct base
{
    void method(int);
    void method(float);
};

struct derived : base
{
    void method(int);
    // base::method(int) is not visible.
    // base::method(float) is not visible.
};

您可以使用using指令解决此问题:

class derived : public base
{
    using base::method; // bring all of them in.

    void method(int);
    // base::method(int) is not visible.
    // base::method(float) is visible.
};

由于您似乎坚持参数数量,我将解决这个问题。 这不会改变任何事情。观察:

struct base
{
    void method(int){}
};

struct derived : base
{
    void method(int,int){}
    // method(int) is not visible.
};

struct derived_fixed : base
{
    using base::method;
    void method(int,int){}
};

int main(void)
{
    {
        derived d;

        d.method(1, 2); // will compile
        d.method(3); // will NOT compile
    }
    {
        derived_fixed d;

        d.method(1, 2); // will compile
        d.method(3); // will compile
    }
}

无论参数或返回类型如何,仍然被遮蔽;它只是阴影的名称using base::<x>;会将所有base的“<x>”方法置于可见状态。

答案 1 :(得分:2)

你遇到了一个经典问题。您的CChild课程需要using CParent::doIt;。我会仔细研究重复的问题。

编辑:

以下是我对基本相同问题的回答:Overriding a Base's Overloaded Function in C++

答案 2 :(得分:1)

我以前从未在基类中使用过该方法。我认为在派生类中添加“使用CLASS :: METHOD”将允许您访问重载方法的其他版本。

class CParent
{
 public:
  void doIt(int x);
};
class CChild : public CParent
{
 public:
  void doIt(int x,int y,int z);

  using CParent::doIt;
};

答案 3 :(得分:0)

问题是CChild实际上并未从CParent继承。

因此它没有只占用一个参数的doIt方法。

答案 4 :(得分:0)

当您覆盖派生类中的函数时,只有派生类中的该函数对该类的用户可见。基类版本变为隐藏。

因此,调用doIt(int x)的pChild指针将失败,因为您使用派生类指针来调用基类函数。调用doIt(int x)的pParent指针将起作用,因为您使用基类指针来调用基类函数。即使你有一个子对象被父指针指向(upcasted),这里的类类型由指针的声明决定。

为了能够使用派生类指针调用该基类函数,您可以:

  1. 在函数调用中限定基类名称,如下所示:

    pChild->CParent::doIt(123);

  2. 使用using指令将基类中的函数名称引入派生类,如前面的帖子所示。

答案 5 :(得分:0)

我理解这种行为是为了让您灵活地覆盖派生类中基类方法的行为。

让我们假设您在基类中有一个函数foo(int),并且您希望在派生类中更改此函数的行为。现在,如果派生类方法没有隐藏基类方法(它具有与基类方法相同的原型),则会在重载决策中引入歧义。

答案 6 :(得分:-2)

您的子类中的方法具有与您尝试传递给它的参数数量不同的参数。它可能与此有关吗?