【问题标题】:Calling overridden function and using overloaded variable from base class调用重写函数并使用基类中的重载变量
【发布时间】:2017-09-27 12:47:55
【问题描述】:

我有两个基类和派生版本,它们像这样重载/覆盖某些部分:

class base
{
public:
    int X = 1;
};

class deriv : public base
{
public:
    int X = 2;
};

class A
{
public:
    base K;
    virtual void doSmth()
    {
        std::cout << "A" << std::endl;
        smthElse();
    }

    virtual void smthElse()
    {
        std::cout << K.X << std::endl;
    }
};

class B : public A
{
public:
    deriv K;
    void doSmth()
    {
        std::cout << "B" << std::endl;
        smthElse();
    }
};

应用程序看起来像这样

int main()
{
    A instanceA;
    B instanceB;

    instanceA.doSmth();
    instanceB.doSmth();

    getchar();
    return 0;
}

因此,AB 两个实例的输出为 X=1。我想知道为什么会这样。 A 使用 base (X=1) 和 B 使用 deriv (X=2)。 deriv 重载 XB 重载 K。是不是因为函数smthElse()只定义在A中,所以A无法知道重载变量K的存在?

如果是这样,函数smthElse() 有没有办法使用重载变量K? 我找到了using 关键字,但还在B 中添加using A::smthElse; 不会改变X 的行为,而不是打印为2。我可以实现这一点的唯一方法是复制函数smthElse() from A 并将其插入B。 有没有不同的方法来实现我正在寻找的东西?因为将相同的函数复制“n”粘贴到B 中只是为了使用被覆盖的变量似乎有点过头了。

提前致谢!

【问题讨论】:

  • 虽然您可以拥有多态成员函数(使用 virtual 关键字),但成员变量不能拥有相同的成员函数。每个类都有自己的独立成员变量KB中的那个与A中的完全无关。
  • 同样适用于derived::base::Xderived::X

标签: c++ oop inheritance overriding overloading


【解决方案1】:

instanceB 有两个变量名为 KA::KB::K。但是,基类A 只知道一个KA::K

这解释了输出。

如果是这样,函数smthElse()有没有办法使用重载变量K?

是的,您可以通过在A 中添加一个virtual 函数来返回对base 的引用并在base 中添加一个虚拟函数来返回对i 的引用。

class base
{
public:
    int& getX( return X;}
private: 
    int X = 1;
};

class deriv : public base
{
public:
    int& getX( return X;}
private: 
    int X = 2;
};

class A
{
public:
    base& getK() { return K; }
    virtual void doSmth()
    {
        std::cout << "A" << std::endl;
        smthElse();
    }

    virtual void smthElse()
    {
        std::cout << getK().getX() << std::endl;
        //           ^^^^^^^^^^^^^ use the virtual functions
    }
public:
    base K;
};

class B : public A
{
public:
    deriv& getK(){ return K; }
    void doSmth()
    {
        std::cout << "B" << std::endl;
        smthElse();
    }
public:
    base K;
};

PS 我希望这只是好奇,你不要用这种风格编写生产代码。你最终会让自己和任何试图理解你的代码的人感到困惑。

【讨论】:

  • 你也可以避免拥有 2 个X
  • 不错的答案,我很高兴看到我们独立地想到了相同的解决方案。
  • @YSC,谢谢。我注意到当需要两个来获得 OP 想要的行为时,你只停留在虚函数上。
  • 我更喜欢简化示例,让读者专注于建议的解决方案:K 的虚拟 getter。
  • 感谢您的回答。是的,这只是出于好奇,而不是为了生产代码!
【解决方案2】:

当你写作时

virtual void smthElse()
{
    std::cout << K.X << std::endl;
}
  • smthElsevirtual
  • K 不是(成员变量不能是 virtual:它对属性没有意义)。

换句话说,这意味着B::smthElse 将超越A::smthElse,但B::KA::K 是两个不同、不相关且独立的变量。

当在B 的上下文中调用smthElse 时,K 仍然意味着A::K

作为一种解决方案,您可以为Ks 创建一个虚拟访问器:

class base { ...};
class deriv{ ...};

class A
{
    base K;
public:
    virtual const base& theK() { return K; }
    virtual void smthElse() { std::cout << theK().X << "\n"; }
};

class B : public A
{
    deriv K;
public:
    virtual const base& theK() { return K; }
};

B{}.smthElse()被调用时,它会调用B::theK(),这将返回B::K(一个deriv instance)。

【讨论】:

  • 你知道(几乎)一切都可以通过添加抽象层来解决吗?
猜你喜欢
  • 1970-01-01
  • 2011-05-03
  • 2023-01-04
  • 2011-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多