为什么我不能通过继承访问此方法?

时间:2014-07-31 18:06:57

标签: c++ oop inheritance

我有两个简单的类,希望通过传递stuff值来访问公共方法int。为什么我不能用Bar的实例做到这一点?它不应该继承公共方法的东西。类型提示给出了int a参数,但它没有编译。

class Foo
{
public:
    int a;
    void stuff(int a){ std::cout << a << std::endl; }
};

class Bar : public Foo
{
protected:
    void stuff() { std::cout << "hello world"; }
};



void main()
{
    Bar b
    b.stuff(3);
}

4 个答案:

答案 0 :(得分:6)

因为Bar::stuff隐藏了Foo::stuff(只有在执行重载解析时名称才重要,所以忽略参数)。

您可以:

  • 使用using声明
  • 将其带入sope
  • 或者,明确限定呼叫,例如b.Foo::stuff(3);

注意

  • main()必须返回int

#include <iostream>

class Foo
{
public:
    int a;
    void stuff(int a){ std::cout << a << std::endl; }
};

class Bar : public Foo
{
public:
    using Foo::stuff;
protected:
    void stuff() { std::cout << "hello world"; }
};

int main()
{
    Bar b;
    b.stuff(3);
}

或者:

int main()
{
    Bar b;
    b.Foo::stuff(3);
}

答案 1 :(得分:4)

在C ++中,当基类中的一个函数与派生类中的一个函数同名时,可以发生名称隐藏。

函数调用过程的阶段

  1. 名称查找
  2. 重载决议
  3. 访问控制
  4. 只要在派生类Bar中找到名称,名称查找就会停止查找其他名称。因此,Bar::stuff()会隐藏stuff中名称为Foo的任何函数。

    在名称查找过程之后,

    • 重载决议失败,因为stuff(int)中没有Bar
    • 即使调用stuff()没有int参数,访问控制也会失败,因为stuff()受到保护。

答案 2 :(得分:4)

查找名称stuff时,Bar中的名称首先找到。找到后,将检查访问权限。由于Bar::stuff受到保护,因此您无法在main中使用它。

从草案标准:

  

10.2会员名称查找[class.member.lookup]

     

1成员名称查找确定类范围(3.3.7)中名称( id-expression )的含义。名称查找可能会导致歧义,在这种情况下,程序格式不正确。对于 id-expression ,名称查找从this的类范围开始;对于 qualified-id ,名称查找从 nestedname-specifier 的范围开始。名称查找在访问控制之前进行(3.4,第11条)。

答案 3 :(得分:0)

b.Foo::stuff(3);

或者,你可以做一个技巧来访问任何受保护的:)

void main()
{
    Bar b;
    class BarAccess : public Bar { friend void main(); }
    BarAccess * ba = reinterpret_cast<BarAccess *>(&b);
    ba->stuff(3);
    ba->stuff();
}