【问题标题】:Abstract base class member function called from derived class从派生类调用的抽象基类成员函数
【发布时间】:2017-06-19 20:54:47
【问题描述】:

我仍在尝试掌握抽象基类的概念以及派生类可以做什么和不能做什么。

我有以下代码:

class NpBaseTest {
    ...
    friend std::ostream& operator<<(std::ostream &os, const NpBaseTest& p_npBaseTest);
    /* Implemented in the .cpp file as -
    std::ostream& operator<<(std::ostream &os, const NpBaseTest& p_npBaseTest)
    {
        p_npBaseTest.show(os);
        return os;
    }
    */
    virtual uint16_t process(int) const = 0;

    virtual void show(std::ostream& os) const
    {
        os
            << "Test ID [" << get_test_id() << "] "
            << "Module Type [" << get_module_type() << "]" << std::endl;
    }
};

class CavTest : public NpBaseTest
{
    ...
    friend std::ostream& operator<<(std::ostream &os, const CavTest& p_cavtest);
    /* Implemented in the .cpp file as
    std::ostream& operator<<(std::ostream &os, const CavTest& p_cavtest) 
    {
        p_cavtest.show(os);
        return os;
    }
    */

    uint16_t process(int p_val) const
    {
        //...implemented here
    }

    void show(std::ostream& os) const
    {
        NpBaseTest::show(os);
        os
            << "CavTest Type" << std::endl;
    }
};

我希望在派生类 show 函数中执行的操作,从基类调用 show 函数,但出现以下错误。 我的理解是,由于 NpBaseTest 是一个 ABC,它在实例化 Derived 类对象时不会实例化对象。 那么我有哪些选择来实现所需的功能?

错误信息:

components/cavium/CavTest.cpp:在函数“void show(std::ostream&)”中: components/cavium/CavTest.cpp:20:错误:无法调用成员函数 'virtual void NpBaseTest::show(std::ostream&) const' 没有对象

更新: 最初的问题解决了。 寻求更多建议 有没有更好的方法来调用基类函数而不必使用 this->::show(os) 指定基类名称?

解决方案: 我将基类show() 例程更改为非虚拟私有成员函数,该函数又调用每个派生类实现的纯虚拟show_all(ostream &amp;os) 函数。这样我就不必为每个派生类重新定义operator&lt;&lt;,并且可以避免使用&lt;BaseClassName&gt;::show()

基类中的示例 -

void NpBaseTest::show(std::ostream& os) const
{
    //Do base functionality here
    os
        << "Test ID [" << get_test_id() << "] "
        << "Module Type [" << get_module_type() << "]" << std::endl;

    // Call derived class routine here
    show_all(os); //This is declared as virtual void show_all(ostream& os) const = 0;
}

在派生类中

void CavTest::show_all(std::ostream& os) const
{
    os
        << "CavTest Type" << std::endl;
}

【问题讨论】:

  • 请将您的程序缩减为最小的完整程序,以显示错误。请edit您的问题并将整个短程序复制粘贴到您的问题中。请将任何错误消息复制粘贴到您的问题中。请参阅minimal reproducible example 了解更多信息。
  • 试试this-&gt;NpBaseTest::show(os);。但它实际上应该根据您显示的内容进行编译。
  • @MooingDuck 正如我所说,在声明中, class::function 不是必需的,因为实现已经在类声明中 - 我不是指函数调用我>
  • @ImNot 只是出于好奇:您使用的是哪个编译器?如前所述,this-&gt; 对于继承的虚函数覆盖应该是隐式的。
  • 是的。这曾多次引起混乱(至少对我而言)。我习惯于相信缩进,但在这里我绝对不应该依赖它。叹息。

标签: c++ inheritance abstract-class


【解决方案1】:

如图所示,您当前的问题与抽象(又名纯虚拟)方法无关,因为没有涉及这些方法。

问题一:成员函数声明语法

基类show() 有一个额外的NpBaseTest:: 限定符,它不应该存在。当你在类声明之外定义一个成员函数时,你只需要那个额外的限定符。通常的情况:

// Foo.hpp
class Foo
{
    void bar();
}

// Foo.cpp
#include "Foo.hpp"
void Foo::bar()
{
    // ...
}

这是您显示错误消息的最可能原因。

问题 2:可见性

基类show() 是私有的,因为在class 中默认可见性是private。您不能从派生类调用私有基类方法,即您对 NpBaseTest::show() 的调用(尽管语法正确)不会编译。

问题3:类声明语法

两个类声明都缺少一个 ;在他们的右大括号之后。

编译它的基本改动是:

class NpBaseTest
{
protected: // or: public:
    virtual void show(std::ostream& os) const { /*...*/ }
};

class CavTest : public NpBaseTest
{
    // private by default
    // Works because you can override with a lower visibility,
    // but not with a higher one.

    void show(std::ostream& os) const override
    {
        NpBaseTest::show(os);
        // ...
    }
};

override 是可选的,但如果您使用支持 C++11(即非古代)的编译器,强烈建议您使用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-19
    • 1970-01-01
    相关资源
    最近更新 更多